Home > Back-end >  Unable to read from external text file
Unable to read from external text file

Time:08-08

So i've got a dynamically allocated array of a struct type (lets call it structtype), and I was trying to read to it from an external text file. structtype looks something like this:

{
    char itemName[15];
    char status;
    int itemAmt;
    char tried;
    char desc[130];
    int rating;
}

And the text file looks something like this: SomeName: y | 3 | Hello Hello | y | 9

in that exact format. I am trying to read from said text file using this code:

void games::LoadFrom(){ // Loads games from the file into array (AllItems)
        ifstream file_in;
        structtype temparray[15] = {};
        for (int i = 0; i < 15;   i) // Empties out AllItems
                AllItems[i] = {};
        file_in.open("items.txt");
        int i = 0; // Counter
        if (file_in){
                while (!file_in.eof() && i < 15){ // Checks if its the end of the file, or if its the max amount I can store
                        file_in.get(temparray[i].itemName, 15, ':');
                        file_in.ignore(100, '|');

                        file_in >> temparray[i].status;
                        file_in.ignore(100, '|');
                        AllItems[i].status = temparray[i].status;

                        file_in >> temparray[i].itemAmt;
                        file_in.ignore(100, '|');
                        AllItems[i].playerAmt = temparray[i].itemAmt;

                        file_in.get(temparray[i].desc, 131, '|');            // All of this reads in a game from the file, and stores it in the AllItems array
                        file_in.ignore(100, '|');

                        file_in >> temparray[i].tried;
                        file_in.ignore(100, '|');
                        AllItems[i].tried = temparray[i].tried;

                        file_in >> temparray[i].rating;
                        file_in.ignore(100, '\n');
                        AllItems[i].rating = temparray[i].rating;

                          i;

                        file_in.get(temparray[i].itemName, 15, ':');
                        file_in.ignore(100, ':');
                }
                cout << AllItems[0].itemAmt;

        }
        cout << AllItems[0].itemAmt;
        file_in.close();

    }

My Problem is that it doesnt read anything in, and instead leaves everything in the struct object at its zero equivalent.

IMPORTANT IN ORDER TO UNDERSTAND To keep in mind: AllItems is a dynamically allocated array, and I was unable to read stuff to it directly, instead I made a seperate statically allocated array called temparray, which is strictly for transferring info to AllItems

When the loop runs, it runs once, and then exits, even though the text file has about 10 items. Can yall help me figure out how to actually read items in? Thanks!

AHEM AHEM. I know this might be very confusing, so feel free to ask questions Ill answer ASAP.

CodePudding user response:

Here's what your code should look like. I've ignored the AllItems and AllGames arrays, and just concentrated on temparray

    while (!file_in.eof() && i < 15){ // Checks if its the end of the file, or if its the max amount I can store
        file_in.getline(temparray[i].itemName, 15, ':');
        file_in >> temparray[i].status;
        file_in.ignore(100, '|');
        file_in >> temparray[i].itemAmt;
        file_in.ignore(100, '|');
        file_in.getline(temparray[i].desc, 130, '|');            // All of this reads in a game from the file, and stores it in the AllItems array
        file_in >> temparray[i].tried;
        file_in.ignore(100, '|');
        file_in >> temparray[i].rating;
        file_in.ignore(100, '\n');
          i;
    }

Main differences with your code - I've used getline not get so the terminating character (':' or '|') is read and discarded. I've only used ignore after a formatted extraction (i.e. after >>) when it is necessary to discard the trailing separator.

When you are writing this kind of code you have to understand in detail what each reading function does, and how that effects the file format you have. It's not good enough to throw together a bunch of code that is roughly the same as your file format, it has to be exactly right.

EDIT

As pointed out in the comments below the above code has a problem which is how it handles end of file. It makes the common error of testing for eof before a read, not afterwards. Here's a version that tests correctly.

   while (i < 15 &&
        file_in.getline(temparray[i].itemName, 15, ':') &&
        file_in >> temparray[i].status &&
        file_in.ignore(100, '|') &&
        file_in >> temparray[i].itemAmt &&
        file_in.ignore(100, '|') &&
        file_in.getline(temparray[i].desc, 130, '|') &&
        file_in >> temparray[i].tried &&
        file_in.ignore(100, '|') &&
        file_in >> temparray[i].rating &&
        file_in.ignore(100, '\n'))
    {
          i;
    }

In this version only if all reads succeed does the while loop get executed and i get incremented.

A read could fail either because of end of file, or because of a format error. If you need to distinguish those two cases you need some more sophisticated code.

  •  Tags:  
  • c
  • Related