1,105,556 Community Members

infile.eof trouble

Member Avatar
jaclynkinsey
Newbie Poster
4 posts since Jan 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I am having trouble displaying my code that is supposed to be read in from "pgm6.txt" - it looks like it is a continuous loop, but I'm not seeing how/why/where. It's probably something oobvious that I'm just overlooking.

Here is a sample of the text in my external file:
Newland
100000
8000
6000
China
1306042971
19882696
9190809
Croatia
4489000
43000
53000
India
1082144298
27947680
9356253

A sample output is:

Country Name:
Country Population: 100000
Number of Births: 8000
Number of Deaths: 6000

It just repeats, over, and over, and over...and doesn't display my name string.

Any help is appreciated. Thanks!

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

class Country 
{   
   private:
    string name;
    int pop;
    int births;
    int deaths;
   public:
    void setName(string na)
       {name = na;}
    void setPop(int po)
       {pop = po;}
    void setBirths(int bi)
       {births = bi;}
    void setDeaths(int de)
       {deaths = de;}
    string getName()
       {return name;}
    int getPop()
       {return pop;}
    int getBirths()
       {return births;}
    int getDeaths()
       {return deaths;}
};

int main ()
{
   Country info;
   int newPop, infoPop, infoBirths, infoDeaths;
   string infoName;

   newPop = 0;
   infoPop = 0;
   infoBirths = 0;
   infoDeaths = 0;

   ifstream infile;
   infile.open("pgm6.txt");

   cout << "************************************************" << endl;

    getline (infile, infoName);
    infile >> infoPop;
    infile >> infoBirths;
    infile >> infoDeaths;

   while (!infile.eof())
   {


    info.setName(infoName);
    info.setPop(infoPop);
    info.setBirths(infoBirths);
    info.setDeaths(infoDeaths);

    cout << left << "Country Name: " << setw(20) <<  info.getName() << endl;
    cout << left << "Population: " << setw(15) << info.getPop() << endl;
    cout << left << "Number of Births: " << setw(15) << info.getBirths() << endl;
    //cout << left << "Birth Rate: " << Setw(15) << << endl;
    cout << left << "Number of Deaths: " << setw(15) << info.getDeaths() << endl;
    //cout << left << "Death Rate: " << setw(15) << << endl;
    //cout << left << "New Population: " << setw(15) << << endl;
    //cout << left << "Percent Growth: " << setw(15) << << endl;
    cout << "**************************************************" << endl;

    getline (infile, infoName);
    infile >> infoPop;
    infile >> infoBirths;
    infile >> infoDeaths;
   }

   infile.close();

   return 0;
   }

Inline Code Example Here

Member Avatar
Lerner
Nearly a Posting Maven
2,416 posts since Jul 2005
Reputation Points: 579 [?]
Q&As Helped to Solve: 407 [?]
Skill Endorsements: 16 [?]
 
0
 

It doesn't look like it's a problem with your use of the return value of eof() that's the problem. If you're going to use eof() to control the while loop that's the way to do it.

The problem looks like it's the use of two input methods in the same program. It seems to be something that many beginners have problems with until they are confronted by the nuances and somebody points it out to them. >> leaves the terminating whitespace char in the input buffer. Often that's a newline char. getline() has the newline char as the terminating char by default. Therefore when you mix the two input methods in the same program you need to be sure the input buffer is clear before you call getline. Otherwise when getline() is called after a call to >> it looks like it didn't do anything, when in fact it did exactly what it was designed to do, which, unfortunately isn't what we wanted. To clear the input buffer you can call the ignore() method of streams. Often ignoring just one char is enough, but a more robust version is to ignore some reasonably large number of char and the most sophisticated way is to ignore as many char as possible, that is the maximum size of the input buffer itself. Either that, or just don't mix two input methods in the same program.

Member Avatar
Kashaku
Light Poster
34 posts since Sep 2009
Reputation Points: 0 [?]
Q&As Helped to Solve: 5 [?]
Skill Endorsements: 0 [?]
 
0
 

Replace every

getline (infile, infoName);

with

infile >> infoName;

solves your problem. It goes in an endless loop because the second time getline() is called, a error is returned. So inline.eof() will always be false, so you get while(true), hence the endless loop. This is caused by the pointer in the file you are reading gets messed up by the way you are calling infopop, infobirths and infodeaths. It gets messed up in such way that getline fails, hence keeps returning errors.

However, your coding is unsafe and very messy. Some points:
1. You assume that the file that you are reading always exists and never fails to open. Use if(infile.is_open()) to ensure that the file is actually open.
2. Why do not you read all the input in the while loop, instead of reading the first four lines out of the while loop? At this moment your way of coding also causes another problem that your last country India never gets outputted. The pointer in the readfile has reached the end of the file when he reads the last data, thus he exits the while loop, while your info gets outputted in the next while loop iteration. By reading the all in the input in the while loop, this will also solve that problem.

I hope this answers all your questions.

Member Avatar
histrungalot
Posting Whiz in Training
280 posts since May 2008
Reputation Points: 32 [?]
Q&As Helped to Solve: 36 [?]
Skill Endorsements: 3 [?]
 
0
 

It is the mixing of the getline and operator>>. getline removes the '\n' if found but the last >> does not. So the first one works but the next getline reads the '\n' from the Newland data and then the >> tries to read the next line which is China into an integer. That fails (sets the fail bit) and that is what causes the infinite loop.
Made some changes to fix mixing getline and >>.

getline (infile, infoName);
infile >> infoPop;
infile >> infoBirths;
infile >> infoDeaths;
infile.ignore(numeric_limits<int>::max(),'\n');  // <---- To fix the mixing of getline and >>
while (!infile.eof()) {
  info.setName(infoName);
  info.setPop(infoPop);
  info.setBirths(infoBirths);
  info.setDeaths(infoDeaths);

  cout << left << "Country Name: " << setw(20) <<  info.getName() << endl;
  cout << left << "Population: " << setw(15) << info.getPop() << endl;
  cout << left << "Number of Births: " << setw(15) << info.getBirths() << endl;
  cout << left << "Number of Deaths: " << setw(15) << info.getDeaths() << endl;
  cout << "**************************************************" << endl;

  getline (infile, infoName);
  infile >> infoPop;
  infile >> infoBirths;
  infile >> infoDeaths;
  infile.ignore(numeric_limits<int>::max(),'\n');  // <---- To fix the mixing of getline and >>
}

Output:

$ ./a.out
************************************************
Country Name: Newland             
Population: 100000         
Number of Births: 8000           
Number of Deaths: 6000           
**************************************************
Country Name: China               
Population: 1306042971     
Number of Births: 19882696       
Number of Deaths: 9190809        
**************************************************
Country Name: Croatia             
Population: 4489000        
Number of Births: 43000          
Number of Deaths: 53000          
**************************************************
Country Name: India               
Population: 1082144298     
Number of Births: 27947680       
Number of Deaths: 9356253        
**************************************************
$
Member Avatar
jaclynkinsey
Newbie Poster
4 posts since Jan 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Thanks for all the help. These were all very good suggestions :)

You
This article has been dead for over three months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article