Initializing an array of strings dynamically in C

2020-04-21 07:12发布

问题:

I know I can initialize an array of strings this way:

static const char *BIN_ELEMENTS[5] = {
    "0000\0",           // 0
    "0001\0",           // 1
    "0010\0",           // 2
    "0011\0",           // 3
    "0100\0",           // 4
};

But I need to accomplish that in a dynamic way. Reading the characters from a File, and inserting them into an array. Then copy that array into an array of strings (like above).

So let's say I captured the following chars from a File, and inserted them into an array, like these:

char number[5];
char *listOfNumbers[10];
number[0]='1';
number[1]='2';
number[2]='3';
number[3]='4';
number[4]='\0';

Now I would like to copy the whole content of number, into listOfNumers[0] // meaning that I've stored "1234" in position 0 of listOfNumers. Leaving 9 more positions to store different numbers.

So I would do something like this:

listOfNumers[0] = number; //this actually seems to work.

But since its a huge file of numbers, I need to reuse the array number, to extract a new number. But when I do that, the content previously stored in listOfNumers[0] gets overwritten, eventho I updated the new position for the new number. How can I deal with that?

Here is what I have so far:

char number[5]; // array for storing number
int j=0;        // counter
int c;          // used to read char from file.
int k=0;        // 2nd counter
char*listOfNumbers[10]; // array with all the extracted numbers.
FILE *infile; 

infile = fopen("prueba.txt", "r");

if (infile) {
    while ((c = getc(infile)) != EOF) {
        if(c != ' ' && c != '\n') 
            number[k] = c;
            ++k;
        } // end inner if
        else {
            number[k] = '\0';
            listOfNumbers[j] = number;
            printf("Element %d is: %s\n", j, listOfNumbers[j]); // prints correct value
            ++j;
            k=0;
        } // end else

    } // end while
    fclose(infile);
} // end outer if

printf("\nElement 0 is: %s\n", listOfNumbers[0]);  // fails - incorrect value
printf("Element 1 is: %s\n", listOfNumbers[1]);    // fails - incorrect value
printf("Element 2 is: %s\n", listOfNumbers[2]);    

回答1:

char *listOfNumbers[10]; only reserves memory for 10 pointers to char. And listOfNumbers[j] = number only stores the address of the array number. It does not copy the content of the array number. As number addrs never changes therefore each of the 10 elements of the 'list' point to the same space.

You need to use malloc for each of your 10 element of listOfNumber to reserve space. you need to use strcpy to copy the content of number to the current listOfNumber[k].

listOfNumber[k] = malloc(strlen(number)+1);  // reserve space of len 
strcpy(listOfNumbers[k],number) // copy string 

Do not forget to free each element of listOfNumbers at end... And also take care to the fact that your file may contain more than 10 strings ...



回答2:

What you are doing is that you take a buffer of five chars, take it's address (number decays to a char* in listOfNumers[0] = number;) and store it in an array of ten char*s. Of course, that is not what you wanted to do, as the end result is that all entries in listOfNumbers point to the same buffer and the original memory is lost.

You have two ways to tackle this problem:

  1. Use strcpy() as H2CO3 suggests.

  2. Use dynamic memory allocation. If you are using the glibc, asprintf and an allocating extension to scanf are your friends (it's POSIX 2008).

Generally, I would always advise against using fixed length buffers: I can guarantee you that the time will come when the limit you imposed does not fit the requirements anymore, and then you are in for extended bug hunting parties... and those allocating functions really make life a lot easier.



标签: c arrays