0

I'm writing a program in C that goes through a string and replaces every alphabetical letter with the letter 13 letters after it in the alphabet (so a Caesar cipher, basically).

I'm relatively new to C and I'm having a difficult time working with strings. My issue at the moment is that when I initialize a new string in line 2, for some reason, the string already has random stuff in it. I know this because when I print the string in line 3, I see 3 random characters (and they're not always the same, they change every few code executions).

Here's the relevant part of my code:

    printf("The original string is %s\n", src);
    char *result = malloc(strlen(src) * sizeof(char) + 1);
    printf("Right off the bat, the result string looks like: %s\n", result);
    for (int index = 0; index < strlen(result); index++) 
    {
        result[index] = "\0";
    }
    printf("Now, the result string looks like: %s\n", result);

My loop in lines 4-7 attempts to empty the string by setting every character in it equal to null. Even more strangely, this loop doesn't work, because when I print the string again in line 8, it's still not empty. Now, though, instead of having random junk in it, it's got the letter "j" repeated 4 times in the first 4 spaces of the allocated space.

I'd really appreciate any help with this. Thanks.

Freddy-Y
  • 3
  • 1
  • 1
    `result` points to uninitialized memory but you call `index < strlen(result)`. It's undefined behavior. You already know size of array (you passed it to `malloc()`, you don't need to calculate it once more. – dimich Jul 03 '23 at 03:20
  • 2
    `result[index] = "\0";` should be `result[index] = '\0';`. Please take some time to think about the difference between `"\0"` and `'\0'`. – Some programmer dude Jul 03 '23 at 03:24
  • 2
    Another option is to use `calloc()` instead of `malloc()`. It returns pointer to zeroed memory. – dimich Jul 03 '23 at 03:27
  • 2
    @dimich In fact, it is sufficient to set `result[0] = 0`; no need to null each and every byte of it. The whole loop is unnecessary. Since a null byte terminates C strings, if the first byte is a null, `result` will be a zero-length (i.e. empty) string. – Amadan Jul 03 '23 at 03:28
  • @Amadan Yes, `*result = '\0';` is enough if the goal is to construct empty string. – dimich Jul 03 '23 at 03:31
  • 1
    Actually, skipping a step, it is not even necessary to make an empty string. `result[len(src)] = 0` and setting the other characters with rotated characters would be sufficient to rot-13 a string, as long as you are not planning to print out the intermediate stages of `result`. – Amadan Jul 03 '23 at 03:35
  • Actually, if the goal is to *replace* characters, no need to allocate new string, replace them in existing one. – dimich Jul 03 '23 at 03:40
  • One thing that I think a lot of newer folks struggle with is if you use `malloc` or `calloc` you must remember the size you allocated, there's no portable way to determine how much memory a pointer points to. `int resultLength = strlen(src) + 1; char *result = malloc(resultLength); for (int index = 0; index < resultLength; index++) { ... }` – Retired Ninja Jul 03 '23 at 03:41
  • 1
    @Freddy-Y, Aside: `malloc(strlen(src) * sizeof(char) + 1)` is conceptually wrong. Use `malloc((strlen(src) + 1) * sizeof(char))` or simply: `malloc(strlen(src) + 1)`. – chux - Reinstate Monica Jul 03 '23 at 06:47

1 Answers1

0
char *result = malloc(strlen(src) * sizeof(char) + 1);

At this point we don't even know if malloc succeeded in allocating the memory. If it did, the memory is uninitialized and using it with functions like strlen invokes undefined behavior.

If you want the string to be "empty" at the very least the first character needs to be '\0'. This can be achieved by using calloc rather than malloc.

char *result = calloc(strlen(src)+1, 1); // sizeof(char) is 1
Chris
  • 26,361
  • 5
  • 21
  • 42
  • Using uninitialized memory produces indeterminate values, not undefined behavior. – Eric Postpischil Jul 03 '23 at 10:26
  • @EricPostpischil Indeterminate values may cause `strlen()` to access memory out of array bounds, and it's UB. – dimich Jul 03 '23 at 13:50
  • @dimich: Yes, and the cause of undefined behavior there is `strlen` going out of bounds, not the indeterminate values. We could put determinate values in the array, say `'A'` in each byte, and call `strlen`, and it would still go out of bounds and have undefined behavior, but we do not say determinate values caused that. It is the programmer error that is the base cause, the not the use of determinate values, nor the use of indeterminate values. – Eric Postpischil Jul 03 '23 at 14:06
  • 2
    @dimich: Further, with the indeterminate values, one of them could manifest as zero, and `strlen` would return, and there would be no undefined behavior. So the mere fact that `strlen` is called with an array containing indeterminate values is insufficient to conclude that there will definitely be undefined behavior. Understanding the differences between indeterminate values and undefined behavior is important for debugging. – Eric Postpischil Jul 03 '23 at 14:09