Q:

Implementation improvement on a case switch programme

I can tell that there will be a memory leak on this and am looking for improvements / the standard way of doing things as far as these kind of problems go. 
(e.g. how an experienced / pro use on C would implement this)
This is a simple case switch programme. Its purpose is to give it PizZa and give you back pIZza.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char changeCase(char ch){

    if ( (int)ch < 65 || (int)ch > 122){
        return ch;
    }else if ((int)ch < 91){
        return (char)(ch + 32);
    }
    else{
    return (char)(ch - 32);
    }
}

char* toUpper(char* string){
    size_t size=strlen(string);
    char* temp = (char*) malloc(size);

    while (*string != '\0'){
        *temp = changeCase(*string);
        temp++;
        string++;
    }

    return (temp - size);
}

int main() {

    char* string = toUpper("PIZa");
    printf("%s",string);

    return 0;
}

This results in a memory leak since the memory from malloc is not freed. What would be better? Allocating memory outside the function and giving the pointer to that memory to the toUpper function? Other idea?

A:

The de facto standard rule is that the part of the code that did the dynamic allocation is also responsible for freeing it. So if your function was in some file "toupper.c", then there should have been some manner of clean-up function available in that same C file.
However, the best solutions separates memory allocation and algorithms. This means that a better way to write this function is this:
void toUpper (char* dst, const char* src)
{
  while (*src!= '\0')
  {
    *dst= ...
    ...
    dst++;
    src++;
  }
}

Here, the caller can allocate space for dst as it pleases, it's no business of the algorithm. For example:
char str1[] = "hello world";
char* str2 = malloc(strlen(str1) + 1);
toUpper(str2, str1);
...
free(str2);

Just make sure to document the function so that the caller knows that they have to allocate space for dst - to be at least as large as src.
As a side-note, char* temp = (char*) malloc(size); is wrong, you didn't allocate room for the null terminator. Also your algorithm must make sure to copy the null terminator into the destination buffer.

