2

Apologies if this is simple, but I am new to C. I am trying to create a loop that fills in an empty array of strings with multiple strings. However, at the end, the whole array is being filled with the latest element ! Below is the code:

int main(void)
{
    string array_test[2];
    char string_test[300];

    for (int i = 0; i < 2; i++)
    {
        snprintf(string_test, sizeof(string_test),"Test: %i", i);
        array_test[i] = string_test;
    }

    for (int i = 0; i < 2; i++)
    {
        printf("%s\n", array_test[i]);
    }
}

This returns:

Test: 1
Test: 1

But I am expecting:

Test: 0
Test: 1
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
user9051697
  • 119
  • 8
  • Array assignments don't make copies. You're just setting `array_test[i]` to a pointer to the same `string_test` array every time. – Barmar Jan 12 '21 at 20:15
  • You are setting `array_test[0]` and `array_test[1]` to `string_test`, which itself is a character string. Since you aren't actually making a copy, both elements of `array_test` point to the same string, the latest update of `string_test` – h0r53 Jan 12 '21 at 20:15
  • It would be more obvious if you didn't use the CS50 `string` typedef. – Barmar Jan 12 '21 at 20:15
  • 3
    What is `string`? – bolov Jan 12 '21 at 20:23

3 Answers3

2

Because you are using the same buffer to save strings in all iterations. This will make previous strings overwritten by new strings.

Allocate separate buffers for each strings to avoid this.

/* put #include of required headers here */

int main(void)
{
    string array_test[2];
    char string_test[2][300];

    for (int i = 0; i < 2; i++)
    {
        snprintf(string_test[i], sizeof(string_test[i]),"Test: %i", i);
        array_test[i] = string_test[i];
    }

    for (int i = 0; i < 2; i++)
    {
        printf("%s\n", array_test[i]);
    }
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
1

Why the for loop is filling the whole array with the latest string?

The for loop is filling the whole array of pointers array_test with the address of the first character of the character array string_test.

That is you declared an array of two pointers

string array_test[2];

and each element of the array points to the first character of the same array string_test

array_test[i] = string_test;

The statement above is equivalent to the following statement

array_test[i] = &string_test[0];

That is an array designator used in expressions with rare exceptions is converted to a pointer to its first element.

So you are outputting the same character array string_test using two pointers.

printf("%s\n", array_test[i]);

Instead of the array of pointers you could declare a two-dimensional character array like

char array_test[2][300];

and in the first for loop you could copy strings formed in the array string_test into elements of the array array_test like

strcpy( array_test[i], string_test );

In this case each element of the two-dimensional array will store its own string.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

All elements in the string array point to the same buffer, so they all appear to have the same string, more precisely the value last composed into this buffer.

Using the typedef string for char * creates confusion about this fact, which is one more reason to not hide pointers behind typedefs.

You can allocate a copy of the string in the loop:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *array_test[2];
    char string_test[300];

    for (int i = 0; i < 2; i++) {
        snprintf(string_test, sizeof(string_test), "Test: %i", i);
        array_test[i] = strdup(string_test);
    }

    for (int i = 0; i < 2; i++) {
        printf("%s\n", array_test[i]);
    }

    for (int i = 0; i < 2; i++) {
        free(array_test[i]);
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189