Help filling a structure with data from a file.

This is a discussion on Help filling a structure with data from a file. within the C++ Programming forums, part of the General Programming Boards category; Hello again. I'm having trouble with reading a file containing several different types of data(all part of a structure). This ...

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    163

    Help filling a structure with data from a file.

    Hello again. I'm having trouble with reading a file containing several different types of data(all part of a structure).
    This is the contents of my .txt file
    Code:
    253.99,4478,Video Card,1
    88.99,7789,Motherboard,3
    154.99,4753,CPU,2
    and this is my code
    Code:
         Info p[MAX_NUM_PURCHASES];  
         
         fstream inDataFile;
         inDataFile.open(("C:\\" + yearMonth + ".txt").c_str(), ios::in);
         int numPrint = 0;
         for(int i = 0; i < 5; i++)
         {
             while(!inDataFile.eof())
             {
                  p[i].price = inDataFile.get();
                  p[i].serialNum = inDataFile.get();
                  p[i].descript = inDataFile.get();
                  p[i].order = inDataFile.get();
             }//End while not end of file.
             numPrint++;
         }//!End of for loop
    I've tried several differen't ways of getting the data, but none of them seem to work for me. I want each part of the structure to be filled with the data until there's a comma(","). After the comma it moves on to the next part of the structure. When there's a new line, it moves to the next structure in the array.
    Does anybody have any ideas for this?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    get() will only read a single character. You could use getline with ',' as the delimiter for the first three items, then getline with '\n' as the delimiter for the last one. You could also read the entire line into a string and then use a stringstream to parse the line based on the commas.

    If price is a double (or float) then you'll need to read it in using something other than getline, or convert it afterwards.

    Also, don't use eof() to control your loop. Use the return value of your first read from cin (either getline or operator>>), which will be false if the read failed for any reason, including end of file.

  3. #3
    Registered User
    Join Date
    Aug 2006
    Posts
    163
    Thanks for the reply Daved. I thought I had posted this last night, but apparently it didn't get sent through. I changed up my code. I did some research first, and found the delimiter stuff and I'm pretty sure I understand how it works. It compiles just fine, and the program runs up until the point when I want to read the files, then it crashes(windows has an error and wants me to send a report).

    Code:
         Info p[MAX_NUM_PURCHASES];  
         
         fstream inDataFile;
         inDataFile.open(("C:\\" + yearMonth + ".txt").c_str(), ios::in);
         int numPrint = 0;
         char delimiter;
         string s;
         for(int i = 0; i < 5; i++)
         {    
             while(getline(inDataFile, s))
             {
                  if(s != "")
                  {              
                      getline(inDataFile, s, delimiter = ',');
                      p[i].price = s;
                      getline(inDataFile, s, delimiter = ',');
                      p[i].serialNum = s;
                      getline(inDataFile, s, delimiter = ',');
                      p[i].descript = s;
                      getline(inDataFile, s, delimiter = '\n');
                      istringstream stream1(s);
                      int h;
                      stream1 >> h;
                      p[i].order = h;
                  }//!End if getline does not result in nothing.
             }//!End while not end of file.
             numPrint++;
         }//!End of for loop
    I don't get it. Why would this cause such an error?

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    Code:
         for(int i = 0; i < 5; i++)
         {    
             while(getline(inDataFile, s))
    You realize that this is trying to read the whole file five times? The while(getline()) loop reads the whole file. If you really want to read the whole file five times, then rewind the file at the end of the for loop; otherwise, get rid of the while loop and put an if in (to read 5 lines) or the for loop (to read all lines).
    Code:
    getline(inDataFile, s, delimiter = ',');
    That compiles, but it's redundant; you could just have used
    Code:
    getline(inDataFile, s, ',');
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Aug 2006
    Posts
    163
    Quote Originally Posted by dwks
    You realize that this is trying to read the whole file five times? The while(getline()) loop reads the whole file. If you really want to read the whole file five times, then rewind the file at the end of the for loop; otherwise, get rid of the while loop and put an if in (to read 5 lines) or the for loop (to read all lines).
    Correct you are! I tried taking out the for loop, but the error was still there. So then I kept the for loop and got rid of the while loop. Now there's no error. But, it doesn't put the data into the array like it should. Is there something else wrong with the code?

    Then, I just realized this before posting my code. If I take out the while loop then string s holds no value. so s == "". So it doesn't go through the reading file in the if section. When I set s to "p", it gives me the error again. So, it's gotta be an error there. Any ideas?
    Thanks!

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    If I take out the while loop then string s holds no value.
    Take out the loop, but leave in the getline().
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,262
    Here's a solution, which works with what you posted up as a test file:

    Code:
    // Your struct
    struct Info
    {
    	double price;
    	int serialNum;
    	std::string descript;
    	int order;
    };
    
    // Templated type-cast function
    template <typename T, typename U>
    T lexical_cast ( U src )
    {
    	std::stringstream s;
    	T dst;
    
    	if ( !( s << src ) || !( s >> dst ) )
    	throw std::bad_cast ( "Invalid conversion" );
    
    	return dst;
    }
    
    
    int main ( void )
    {
    	std::ifstream in ( "thing.txt" );
    
    	if ( !in ) 
    	{
    		in.close();
    
    		return 1;
    	}
    
    	std::string temp;
    	Info info;
    
    	while ( getline( in, temp, ',' ) )
    	{
    		info.price = lexical_cast< double, std::string > ( temp );
    		std::cout<< '\n' << "Price: " << info.price;
    
    		getline( in, temp, ',' );
    		info.serialNum = lexical_cast< int, std::string > ( temp );
    		std::cout<< '\n' << "Serial: " << info.serialNum;
    
    		getline( in, temp, ',' );
    		info.descript = temp;
    		std::cout<< '\n' << "Description: " << info.descript;
    
    		getline( in, temp, '\n' );
    		info.order = lexical_cast< int, std::string > ( temp );
    		std::cout<< '\n' << "Order #: " << info.order << '\n';
    	}
    
    	in.close();
    
    	return 0;
    }

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    The original problem is that the getline inside the while loop should be the first getline that reads in the price. Otherwise, you are ignoring a line in the file. Then, you need to have one loop. That loop needs to go until the first getline (for price) returns false, or until i is equal to MAX_NUM_PURCHASES (so you don't go past the array bounds).

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    The while loop should work if you add the delimiter for getline. Plus I just realized you need to initialize and increment i.
    Code:
             int i = 0;
             while(getline(inDataFile, s, ','))
             {
                  if(s != "")
                  {              
                      getline(inDataFile, s, delimiter = ',');
                      p[i].price = s;
                      getline(inDataFile, s, delimiter = ',');
                      p[i].serialNum = s;
                      getline(inDataFile, s, delimiter = ',');
                      p[i].descript = s;
                      getline(inDataFile, s, delimiter = '\n');
                      istringstream stream1(s);
                      int h;
                      stream1 >> h;
                      p[i].order = h;
                      i++;
                  }//!End if getline does not result in nothing.
             }//!End while not end of file.
    Last edited by swoopy; 09-26-2006 at 04:23 PM.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    You should also check i against MAX_NUM_PURCHASES just to be safe and break out of the loop if i gets that big.

    Note that unless you have or expect empty lines in your file, the check for an empty string s is unnecessary. In fact, s should never be empty in swoopy's version of the code. If you have empty lines in your file, your price value will be messed up because it will read until a comma (including newlines). If there are empty lines at the end of the file, getline should fail breaking out of the while loop.

  11. #11
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,262
    Also, as an alternative so that you don't have to check for that MAX_NUM, you could always use a <vector>, which is basically a resizeable array, and, guess what? You don't have to define a MAX_NUM for the array size with them! You can just keep on adding to them. There are lots of examples around the forums if you are interested in looking into them, and sure, the board's here if you are interested and get stuck too

  12. #12
    Registered User
    Join Date
    Aug 2006
    Posts
    163
    Quote Originally Posted by twomers
    Also, as an alternative so that you don't have to check for that MAX_NUM, you could always use a <vector>, which is basically a resizeable array, and, guess what? You don't have to define a MAX_NUM for the array size with them! You can just keep on adding to them. There are lots of examples around the forums if you are interested in looking into them, and sure, the board's here if you are interested and get stuck too
    Awesome. Thanks for all the replies. I'll be checking them out when I get to a computer with a compiler.

    I haven't gotten to vectors or templates yet, but I will be reading up on those soon, to get ahead of the game.
    The professor actually made a mistake in class that I had made a few days ago, and Twomers you showed me how to get around it.
    He had something like this:
    Code:
    int i = something;
    dataFile.open("C:\\" + i + ".txt", ios::out);
    I was the only one who caught the error there(that you can't add an integer to it like that, it's gotta be a string). I got some bonus(I also got some bonus for pointing out that he used void main() on a quiz). So, again, thanks for all the help!

  13. #13
    Registered User
    Join Date
    Aug 2006
    Posts
    163
    Well, I tried your code swoopy. It compiled just fine, and the logic is all there, but windows is giving me an error each time(not the program, just windows and it's error reports). I'm thinking it's something to do with that machine. I've tried it on mine, but it doesn't even run(just sits and takes up 98% of the cpu power until I end it through task manager).

    It should be good enough for an A, and I understand what I was doing wrong before. So there's the two most important things solved(not neccesarily in that order though).
    I'm off to start this take home test. And you can bet I'll be using stuff I learned on here! Thanks!

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    I've tried it on mine, but it doesn't even run(just sits and takes up 98% of the cpu power until I end it through task manager).
    You must not be using the same input file?

    [edit] Psst, twomers, check your PMs. [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    >> not the program, just windows and it's error reports
    That usually means a crash in the program.

    Actually, I do see a bug in swoopy's code. It tries to read in the price twice. The first getline used as the while control reads in the price, but then getline is then called again immediately. That first getline inside the body of the loop should be removed.

Page 1 of 3 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. data structure design for data aggregation
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 05-20-2008, 06:43 AM
  2. Replies: 3
    Last Post: 02-26-2008, 01:12 PM
  3. ordered linked list
    By redmondtab in forum C Programming
    Replies: 48
    Last Post: 10-22-2006, 06:09 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 02:58 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21