Morse Code Converter in C I'm learning C so I thought to apply it to miniproject on reddit. The smorse function takes in a string and spits out some morse code. It works if you supply the function with only lowercase letters. I feel awkward making a first for loop in my smorse function to calculate the size of buffer I need to malloc and then making a second for loop to add the characters.

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

char **master = NULL;

char* smorse(char *str) {
    int i;
    char *ele;
    int end = strlen(str);
    char *output = "";
    int totalSize = 0;

    for (i = 0; i &lt; end; i++) {
        ele = master[(*str) - 97];
        totalSize += sizeof(ele) * sizeof(char);
        str++;
    }

    output = malloc(totalSize);
    str -= end;

    for (i = 0; i &lt; end; i++) {
        ele = master[(*str) - 97];
        strcat(output, ele);
        str++;
    }

    return output;
}

int main(int argc, char *argv[]) {
    int i;
    char key[] = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..";
    master = (char **)malloc(26 * sizeof(char *));
    char *ele = strtok(key, " ");

    for (i = 0; i &lt; 26; i++) {
        if (i != 0)
            ele = strtok(NULL, " ");
        master[i] = (char *)malloc(sizeof(ele) * sizeof(char));
        master[i] = ele;
    }

    printf("%s\n", smorse("sos"));
    printf("%s\n", smorse("daily"));
    printf("%s\n", smorse("programmer"));
    printf("%s\n", smorse("bits"));
    printf("%s\n", smorse("three"));

    free(master);
    return 0;
}
Memory leak
Consider this (I removed the pointless cast and identity multiplication):

    master[i] = malloc(sizeof ele);
    master[i] = ele;


Here, we allocate memory (if malloc() succeeds), but then immediately overwrite our one and only pointer to it, so we're unable to ever free it.  The first assignment should just be removed, leaving only master[i] = ele.
Another memory leak:

printf(&quot;%s\n&quot;, smorse(&quot;sos&quot;));


The smorse() function returns a pointer to allocated memory, which we need to release when we've finished using it:
const char *m = smorse(&quot;sos&quot;);
puts(m);
free(m);

(The puts() call is exactly equivalent to using printf(&quot;%s\n&quot;, m), but more readable and possible more efficient.)
Character coding assumptions
The magic value 97 in a couple of places suggests that we're assuming that characters are encoded as ASCII values.  That's not a portable assumption: C permits a wide range of encodings.  Notably, EBCDIC systems do not have letters in the same positions as ASCII (or even as a contiguous block, so replacing with 'a' doesn't solve the problem).
Also, there's no checking that the input to the function contains only characters that we can handle.  If we pass anything outside of the expected range, then we index master outside its bounds, which is Undefined Behaviour in C.  That means that the program may do anything - if we're lucky, it will simply crash, helping us to identify the problem, but there's no guarantee of that.
We ought to be converting more than just letters - digits have a standard Morse representation, as do certain other useful symbols.
Value conversions
It seems that this has been compiled with a very low level of warnings enabled.  Building with my usual compiler flags results in over a dozen warnings, most about suspect conversions.
To pick a couple of examples:

int end = strlen(str);


strlen() returns a size_t, which is of different signedness to int, and very likely to be bigger, so there's a risk of undefined behaviour here.

char *output = &quot;&quot;;


It's dangerous to point a modifiable pointer at constant data (a string literal is of type char const*).

printf(&quot;%s\n&quot;, smorse(&quot;sos&quot;));


Passing a string literal loses constness here - smorse() ought to accept pointer to const instead.