My assignment this week deals with using a struct. I think I can do that part. What I'm having trouble with is reading the file into each variable.

The first item in the file is text with spaces. The next items are numeric and need to go into other variables, but the entire text (with spaces between words & not necessarily the spaces between the text & the first number) has to go into one string variable (for each line). Then the digits on that line are read into the rest of the variables.

I can get it to work except that the first digit isn't read into the first numeric variable.

Can you tell me a better (or the correct) way of doing this?

int i = 0;

    while (inFile.good() ){ 
        //read a line...but we don't want the whole line, just the non-digit part
        char ch = inFile.get();
        int j = 0;  //on each line... NO NO NO THIS IS WRONG!!!!

        while(isalpha(ch)|| ch ==' '){
            items[i].name[j] = ch;
            j++;
            ch = inFile.get();
        }

        //NOPE! Doesn't add 1st digit... because it's stuck in 'ch' b/c of inFile.get(); ?     
        inFile >> items[i].itemNo >> items[i].qty >> items[i].price >> items[i].safe;  
        i++; 
    }

//I tried these things & it did not work:
//        getline(inFile, items[i].name); //NO!!! Don't want the whole line, just the alpha part!
//        inFile >> items[i].name; // This only inputs ONE word, not the whole name

The contents of the text file:

Wong Batts 98723 243 6.45 200
Widgets No Two 83209 990 17.50 800
HumpBack Whale Songs 74329 42 23.70 50
Frozen Ice Cubes 73922 100 0.15 150
Canned Solar Winds 23923 12 850.00 6
Sented Toe Jamm 18492 14 0.50 20
Backwards Left Turns 87293 5 14.95 12
Meals for Up Chuck 62042 20 16.50 24

I can get it to work except that the first digit isn't read into the first numeric variable.

...and that it only reads the first line (sort of) correctly. It puts the first item into all of the spaces in items[].name, so that items[0].name = "Wong Batts"
items[1].name = "Wong Batts"
etc.

...and after the first line, qty, price and safe do not contain the correct amounts.

>> //NOPE! Doesn't add 1st digit... because it's stuck in 'ch' b/c of inFile.get();

call inFile.unget() to put the digit back onto the stream.

Ah...thank you, that works.

But the program still isn't reading more than just the first line. Any idea why?

char ch = inFile.get();
    int i = 0;
    while (inFile){ //while(inFile.good()){ = no change //while(!inFile.eof()){ = infinite loop
 
        //read a line...but we don't want the whole line, just the non-digit part

        while(isalpha(ch)|| ch ==' '){
            items[i].name += ch;
            ch = inFile.get();
        }

        inFile.unget(); //retrieve the last character read, which is the first digit 
        //add the rest of the items to the items array          
        inFile >> items[i].itemNo >> items[i].qty >> items[i].price >> items[i].safe;  
        i++;
        //TEST:
        cout<<"i: "<<i<<endl; //why does it stop after the 2nd iteration?
    }

It probably has to do with the implementation of unget(), though since I don't know how unget() is implemented I don't know that for sure. Having said that, if unget() puts the last value of ch back in the input buffer, but doesn't take the last value of ch out of ch, then ch will still be a nonalpha char at the end of the loop, and that will block further input into the inner while loop. So, try putting another call to get() at the end of the loop to reseed the value of ch before going back to the top of loop, which is sort of like the way you seeded the vaule of ch before entering the loop in the first place.

Are you not allowed to use cin to get whole strings from an input file? cin >> someString; If you are, you could fetch an entire string at a time and process each string individually.

I think it would be a lot simpler to use getline() to read an entire line, then parse its contents. With this you don't have to worry about unget().

string line;
while( getline(infile, line) )
{
    // parse the string here, similar to the way you did
    // it in your original program.

}

After you read the last number, you still have the end-of-line in the file. here's where getline() can clean up the EOL. Since you didn't describe in detail what's really happening with the second line, that's my guess.

But using getline() to read each line and parsing the line is still the better solution.

I kinda like unget(), just because I never used it before. It's like a new thing to play with..."hey, I didn't know you could do that!" kind of thing. lol

Here is what my instructor said:

// ... now if you loop up to the while at this point (your old code) 'ch' still has a digit in it from earlier and it kills the
// .... 'while(isalpha...' immediately and as a matter of fact you never get passed the \n or cr at end of line: infinite loop
// ... this is why you never read the next item
// ch = inFile.get(); ... this read get past the cr at the end of line just read.
// ch = inFile.get(); ... this read gets the first char of the next item name which you need as a prime for the big while loop above.

Still it would make more sense to me not to have to use inFile.get() twice in a row like that. I expect that y'all are correct in saying that it would be better to use getline() & then just parse the line.

Thanks for the advice.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.