Home > Mobile >  Reading lines of txt file into array prints only the last element
Reading lines of txt file into array prints only the last element

Time:10-07

First of all, I didn't code in C for more then 8 years, but there is a hobby project I would like to work on where I ran into this issue.

I checked a similar question: Only printing last line of txt file when reading into struct array in C but in my case I don't have a semicolon at the end of the while cycle.

Anyway, so I have a nicknames.txt file where I store nicknames, one in each line. Then I want to read these nicknames into an array and select one random element of it. Example nicknames.txt:

alpha
beta
random nickname
...
Pirate Scrub

Then I read the TXT file:

    int nicknameCount = 0;
    char *nicknames[2000];

    std::string line;
    std::ifstream file("nicknames.txt");
    FILE *fileID = fopen("asd.txt", "w");

    while (std::getline(file, line))
    {
        nicknames[nicknameCount  ] = line.data();
        // (1)
        fprintf(fileID, "%i: %s\n", nicknameCount - 1, nicknames[nicknameCount - 1]);
    }

    int randomNickIndex = rand() % nicknameCount;

    // (2)
    for (int i = 0; i < nicknameCount; i  )
        fprintf(fileID, "%i: %s\n", i, nicknames[i]);

    fprintf(fileID, "Result: %s\n", nicknames[randomNickIndex]);
    fprintf(fileID, "Result: %i\n", randomNickIndex);
    fclose(fileID);
    exit(0);

What then I see at point (1) is what I expect; the nicknames. Then later at point (2) every single member of the array is "Pirate Scrub", which is the last element of the nicknames.txt.

I think it must be something obvious, but I just can't figure it out. Any ideas?

CodePudding user response:

line.data() returns a pointer to the sequence of characters. It is always the same pointer. Every time you read a new line, the contents of line are overwritten. To fix this, you will need to copy the contents of line.

Change:

char *nicknames[2000];

to

char nicknames[2000][256];

and

nicknames[nicknameCount  ] = line.data();

to

strcpy(nicknames[nicknameCount  ], line.data());

However, using a vector to store the lines is probably better, since this is C

CodePudding user response:

Your nicknames array does not contain copies of the strings, all the nicknames are pointers to the same data owned by line.

Instead of char* nicknames[2000] i would recommend you use

std::vector<std::string> nicknames;

and then inside the loop:

nicknames.push_back(line);

CodePudding user response:

This:

char *nicknames[2000];

is an array of 2000 pointers to char. Nowhere in your code you are actually storing the strings from the file. This

nicknames[nicknameCount  ] = line.data();

merely stores pointers to the lines internal buffer in the array. In the next iteration this buffer is overwritten with contents of the next line.

Forget about all the C i/o. Mixing C and C is advanced and you don't need it here. If you want to store a dynamically sized array of strings in C , that is a std::vector<std::string>:

 std::vector<std::string> lines;
 std::string line;
 while (std::getline(file, line))
 {
    lines.push_back(line);
 }

Also for writing to the output file you should use an std::ofstream.

  •  Tags:  
  • c
  • Related