-1

I am perplexed that the following code is not behaving as expected.

The code behaves differently depending on how the string is initially defined (i.e. char str[] = "1,000" vs char *str = "1,000").

Here is the code:

#include <stdio.h>

char* removeCommasInString (char *str);

int main()
{
    char str[] = "1,000,000";
    char str2[] = "10,000";
    char* str3 = "1,000";
    
    printf("str is %s\n", str);
    printf("str is %s\n\n", removeCommasInString(str));
    
    printf("str2 is %s\n", str2);
    printf("str2 is %s\n\n", removeCommasInString(str2));
    
    printf("str3 is %s\n", str3);
    printf("str3 is %s\n", removeCommasInString(str3));
   
    puts("Program has ended");

    return 0;
}

char* removeCommasInString (char *str)
{
    const char *r = str;    // r is the read pointer
    char *w = str;          // w is the write pointer
                                                
    do {
        if (*r != ',')   
                         
        {
            *w++ = *r;   // Set *w (a single character in the string) to *r
        }
    } while (*r++);      // At end of the string, *r++ will be '\0' or 0 or false
                         // Then loop will end
                         // The str string will now have all the commas removed!!
                         // The str pointer still points to the beginning of the
                         // string.
                             
    return str;
}

Here is the output I get:

str is 1,000,000
str is 1000000

str2 is 10,000
str2 is 10000

str3 is 1,000


...Program finished with exit code 0
Press ENTER to exit console.

The commas are not removed in str3. And the main() function never reaches the "puts" statement. And I never see an error message.

I am sure it is something simple that I am missing.

RobK
  • 156
  • 1
  • 9
  • 1
    You can’t modify string literals reliably. Usually, your program will crash when you try to do so. – Jonathan Leffler Jul 24 '21 at 13:59
  • "*The code behaves differently depending on how the string is initially defined*" -- yes, that seems likely. The alternatives presented are not equivalent. One gives you (directly) a modifiable array of `char`, and the other gives you a pointer to an array of `char` whose elements you must not attempt to modify lest undefined behavior ensure. – John Bollinger Jul 24 '21 at 14:00
  • Both duplicates are part of [the C tag info](https://stackoverflow.com/tags/c/info) FAQ. It might be worth going through all items in the FAQ as it might also answer other questions might have, or help you understand other things you have trouble with. – Some programmer dude Jul 24 '21 at 14:05
  • Thanks for all the explanations. I forgot that char* creates a pointer to a literal array that cannot be changed!! I knew it was something simple. P.S. I also tried "char *str3;" and "strncpy(str3, "1,000", 6);" after adding "#include ". That also does not work because the "char *str3;" creates a pointer to a string that cannot be ever changed. I needed to change "char *str3;" to "char str3[256];". The latter creates an array that can be changed. – RobK Jul 24 '21 at 14:20
  • I forgot to mention that there is an error in the program. I should have added "const" when defining the str3 pointer. (i.e. const char* str3 = "1,000"; ). Once the "const" keyword is added, the compiler will not even let the program compile. This is preferred than having the program crash and trying to figure out what happened! Lesson Learned --- When defining pointers to unmodifiable literal strings, always use the "const" keyword!! – RobK Aug 01 '21 at 15:23

1 Answers1

0
char* str3 = "1,000";

is basically the same as

char* str3 = (char*)"1,000";

since it is pointing to a string litteral (const char*), whereas the others allocate the memory at runtime, so they are modifyable. String litterals are not stored on the stack or heap, instead, they are stored in read only memory, so they cannot be modified.