Problem with struct and ifstream

I'm having trouble with saving the contents of Drinks.txt into the struct Drinks. At the moment the code doesn't compile and I tried everything I could think of; at one point I was making my program crash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Drinks
{
     string soda;
     double price;
     int amount;                           
};

void readAndDisplayMessage(Drinks *);

int main(int argc, char *argv[])
{
     Drinks drinkChoices[5];
     Drinks *ptrDrinkChoices; 
     ptrDrinkChoices = &drinkChoices[5];
     
     
     readAndDisplayMessage(ptrDrinkChoices);
       
    
     system("PAUSE");
     return EXIT_SUCCESS;
}

void readAndDisplayMessage(Drinks *ptrDrink)
{
     string drink; 
     ifstream myFile;
     myFile.open("Drinks.txt");
     if (!myFile)
		{
		     cout << "Cannot load file!" << endl;
		     system("PAUSE");
			 exit(0);
		}
	 for (int i=0; i<5; i++)
     	{
	         getline(myFile, ptrDrink[i].soda, ',');
	         getline(myFile, ptrDrink[i].price, ',');
	         getline(myFile, ptrDrink[i].amount, ',');
        }		
     
     cout << "Welcome!" << endl;
     cout << "Please choose one of the following options:" << endl;
     cout << "Drink Name" << "\tCost" << "\tNumber in machine" << endl;
     
     for (int i=0; i<5; i++)
         {
              cout << ptrDrink[i].soda
                   << "\t" << ptrDrink[i].price 
                   << "\t" << ptrDrink[i].amount 
                   << endl;
         }
     
     myFile.close();  
}
closed account (j3Rz8vqX)
You may be reading data from your file, in a way that you aren't intending to.

The function std::getline take two arguments, not three:
http://www.cplusplus.com/reference/string/string/getline/

Are there any spaces in your text file? or newlines?

An option would be to read a line from the file, then parse it into your three variables.

You can read a whole line with this:
1
2
string temp;
getline(myFile, temp);


Then you could simply parse it (hopefully you've learnt this) and store it into the three variables.

Parsing:
-Find the index of the delimiter, in your case ',' and copy the substring from index_start to the delimiter, exclusive of delimiter. Then set index_start to your delimiter plus 1 so you don't include it.

substr take two arguments:
http://www.cplusplus.com/reference/string/string/substr/

You should know the strings length.
http://www.cplusplus.com/reference/string/string/length/


String reference:
http://www.cplusplus.com/reference/string/string/
I just started learning C++ 4 months ago so I don't know parsing yet, sorry.
closed account (j3Rz8vqX)
Okay.

So possibly try to acquire a single string for now and then learn to manipulate it afterwards?

example:
1
2
3
4
5
6
7
8
9
10
11
12
//Assuming 5 lines in the file.
        //Reading a whole string from file:
        for (int i=0; i<5; i++)
        {
            getline(myFile, ptrDrink[i].soda);
        }

        //Printing the whole string - ensures you've got the data:
        for (int i=0; i<5; i++)
        {
            cout << ptrDrink[i].soda<<endl;
        }

//The above code was not tested, simply written in text box.

First read strings from the file, then you can should how you want to manipulate it later.
Last edited on
Line 21: You're pointing to an entry that doesn't exist. You allocated 5 occurrances at line 19. Those entries are 0-4.

Line 24: You're passing an invalid pointer to readAndDisplayMessage.

Lines 42-47 and 53-59. You're indexing past valid entries. Since the pointer that was passed was to drinkChoices[5], you're now attempting to access drinkChoices[5]-[9], which don't exist.

Lines 45-46: getline does not have overloads for doubles and ints.
Thanks for the help Dput and AbstractionAnon, with your help I managed to print the contents of the file.

Now I want to store those contents into the structure Drinks.
This is what the file contains.

1
2
3
4
5
Cola,0.75,10
Beer,0.75,10
Sprite,0.75,10
Water,0.50,10
Juice,0.95,10


I'm trying to separate the string and get 0.75, so I can store it into double price, by using atof function but I'm only getting the first zero.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Drinks
{
     string soda;
     double price;
     int amount;                           
};

void readAndDisplayMessage(Drinks *);

int main(int argc, char *argv[])
{
     Drinks drinkChoices[5];
     Drinks *ptrDrinkChoices; 
     ptrDrinkChoices = &drinkChoices[0]; // changed it from 5 to 0
     
     
     readAndDisplayMessage(ptrDrinkChoices);
       
    
     system("PAUSE");
     return EXIT_SUCCESS;
}

void readAndDisplayMessage(Drinks *ptrDrink)
{ 
     ifstream myFile;
     myFile.open("Drinks.txt");
     if (!myFile)
		{
		     cout << "Cannot load file!" << endl;
		     system("PAUSE");
			 exit(0);
		}
	 for (int i=0; i<5; i++)
     	{
	         getline(myFile, ptrDrink[i].soda);
                 ptrDrink[i].price = atof("ptrDrink[i].soda");
	       
        }		
     
     cout << "Welcome!" << endl;
     cout << "Please choose one of the following options:" << endl;
     cout << "Drink Name" << "\tCost" << "\tNumber in machine" << endl;
     
     for (int i=0; i<5; i++)
         {
              cout << ptrDrink[i].soda << endl;
                   
         }
     
     myFile.close();  
}
If the first sequence of non-whitespace characters in str does not form a valid floating-point number as just defined, or if no such sequence exists because either str is empty or contains only whitespace characters, no conversion is performed and the function returns 0.0.

Line 43: You're passing a quoted string to atof. There is no valid float at the beginning of that quoted string, so atof is going to return 0. The easiest way to deal with comma separated values is with stringstream.

1
2
3
4
5
6
7
8
9
  string line;
  getline (myFile, line);  // read line into temp string 
  stringstream ss (line);   
  ss.getline (ptrDrink[i].soda, ',');  // get soda name 
  string temp;
  ss.getline (temp, ',');  // get price 
  ptrDrink[i].price = atof (temp.c_str());   // convert string to float
  ss.getline (temp, '\n');  // get quantity
  ptrDrink[i].amount = atoi(temp.c_str());  // Convert string to int 

closed account (j3Rz8vqX)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        //Assuming 5 lines in the file.
        //Reading a whole string from file:
        //Parsing the "temp" string into three parts:
        for (int i=0; i<5; i++)
        {
            string temp;
            int x=0, y=0;
            getline(myFile, temp);
            for(x=0;x<temp.length();x++)//find the first comma
            {
                if(temp[x]==',')
                {
                    break;
                }
            }
            ptrDrink[i].name= temp.substr(y,x-y);
            x++;
            y=x;
            for(x;x<temp.length();x++)//find the second comma
            {
                if(temp[x]==',')
                {
                    break;
                }
            }
            ptrDrink[i].price = atof(temp.substr(y,x-y).c_str());
            x++;
            y=x;
            ptrDrink[i].price = atoi(temp.substr(y,x-y-1).c_str());//assume the last value extends to the end of the string.
        }

        //Printing the whole string - ensures you've got the data:
        for (int i=0; i<5; i++)
        {
            cout << ptrDrink[i].soda<<endl;
            cout << ptrDrink[i].price<<endl;
            cout << ptrDrink[i].amount<<endl;
        }

//Again the above code was not tested, simply written in the text field.

Might work.
Thanks again AbstractionAnon but I was getting a compiler error after I #include <sstream>

Dput, the code prints but ptrDink[i].price prints 10(this should be in amount) and ptrDink[i].amount prints garbage. ptrDink[i].soda prints correctly.

Edit:
Never mind I found the problem
1
2
3
4
ptrDrink[i].price = atof(temp.substr(y,x-y).c_str());
x++;
y=x;
ptrDrink[i].price = atoi(temp.substr(y,x-y-1).c_str());//assume the last value extends to the end of the string. 


Thank you sincerely for the help AbstractionAnon and Dput.
Last edited on
closed account (j3Rz8vqX)
Yeah, code on the fly can be incorrectly posted.

Copy and pasted.

You get my intentions though =D
Topic archived. No new replies allowed.