0

I've been giving an... interesting... task. I've been asked to modify a character array using a pointer.

I'm aware that:

*char = "something"; //is a literal and cannot be modified.

char[] = "something"; //can be modified

But what about:

main.c
------

static char* stringlist01[] = 
{
    "thiy iy a ytring",
    "this is also a string, unlike the first string",
    "another one, not a great one, and not really like the last two.",
    "a third string!",
    NULL,
};

int main()
{
    int ret = 9999;

    printf("////TEST ONE////\n\n");

    ret = changeLetterInString(stringlist01[0]);
    printf("Return is: %d\n\n", ret);

    printf("Stringlist01[0] is now: %s\n", stringlist01[0]);
}

AND

changeLetterInString.c
----------------------

int changeLetterInString(char *sentence)
{    
    if (sentence != NULL)
    {
        // TODO
        // Need to change "thiy iy a ytring"
        // into "this is a string"
        // and save into same location so
        // main.c can see it.
    }

    success = 0;    // 0 is Good
    return success;
}

So far, I've tried:

    for (char* p = sentence; *p; ++p)
    {
        if (*p == 'y')
        {
            *p = 's';
        }
    }

And I've tried:

sentence[0] = 't'
sentence[1] = 'h'
sentence[2] = 'i'
sentence[3] = 's'   // and so on...

But neither work.

Any help and/or insight would be greatly appreciated.

Stryker2k2
  • 108
  • 9
  • 1
    Literal strings in C are effectively *read-only*, as they are not allowed to be modified. And you have an array of *pointers* to such string literals (or rather pointers to their first characters). Any attempt of modifying a string literal leads to *undefined behavior*. This is the reason that all such pointers should be `const char *`. – Some programmer dude Nov 18 '19 at 15:32
  • A string literal is constant. You cannot modify it. If you want to modify it, you need to read it like an array – Frontear Nov 18 '19 at 15:39
  • Thank you @Someprogrammerdude for your insight! – Stryker2k2 Nov 18 '19 at 16:07
  • You could do `(char[]){ "thiy iy a ytring" }`. This creates a compound literal which is essentially a local array existing in the same scope as it was declared. It is read/write but you can't change the length. The most flexible solution is to use dynamic allocation + strcpy. – Lundin Nov 18 '19 at 16:13
  • (same question as [Why do I get a segmentation fault when writing to a "char \*s" initialized with a string literal, but not "char s\[\]"?](https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-char-s-initialized-with-a)) – user202729 Jun 18 '22 at 11:39

1 Answers1

2

There are subtle differences between the two notations:

char string[] = "Hello World";
// vs
char* string = "Hello World";

They look similar enough, right? However they are different. The first one is an array of characters, whereas the second one is a pointer to an array of characters.

By default, any string literal will always be const. No way around it. Trying to modify a string literal will usually result in a segfault.

Your code contains an array of pointers to an array of characters. Since you contain pointer references to constant string literals, you cannot modify them. In order to modify them, you need to convert them into an array instead, like how it's done in the first example. This will transform the string literal to an array of characters, that can be modified, rather than being a pointer to memory which cannot be modified.

char strs[][] = {
    "Hello",
    "World"
}; // transforms the string literals into character arrays

strs[0][0] = 'X'; // valid

Whereas this would not compile, and caused undefined behaviour

char* strs[] = {
    "Hello",
    "World",
};

strs[0][0] = 'X'; // trying to modify a pointer to a constant string literal, undefined
Frontear
  • 1,150
  • 12
  • 25