Reputation:
I have a file whose content looks like this :
Aadam
50
Aadam
0
Aad
0123
Waleed
12345
Now, I need to store first line in a string array and second line into an integer array. This is the source code that I have written....
ifstream infile ("File.txt");
string name [20];
int score [20};
for (int i = 0; !infile.eof(); i++)
{
getline(infile, name[i]);
infile >> scores[i];
}
Well, the program reads first line successfully but after that it does nothing. I tried another method first, in which I store the integer first as a temporary string and then I convert that string into an integer using "stoi", which worked like a charm. Like this :
for (int i = 0; !infile.eof(); i++)
{
getline(infile, name[i]);
string temp;
getline(infile, temp);
scores[i] = stoi(temp);
}
But the problem is that I can't use stoi. It works fine in my computer but I have to provide the source code to my teacher who may not have the compiler which supports C++11. Which may be a problem for me. So I need another way to input data from the file. So, Kindly if you know a way to do this, please show me the way.
Upvotes: 0
Views: 843
Reputation: 141648
The gist of the problem is that if the input contains:
Aadam\n
50\n
and you do:
getline(infile, name[i]); // name[i] contains "Hello", \n consumed
infile >> scores[i]; // scores[i] contains 50
then the input still contains:
\n
that was after the 50
. The >>
operator with int
does not consume any trailing newlines or other characters after the number that it extracted.
Then for the next time around the loop, the input stream contains:
\n
Aadam\n
0\n
and you do:
getline(infile, name[i]); // name[i] contains "", \n consumed
infile >> scores[i]; // input failure
Since Aadam
(the second one) cannot be parsed as an int
, the >>
operator puts infile
into a failure state. Your code never clears the failure state nor checks for it, so all subsequent operations fail and your code goes into an infinite loop.
Additional problems are that using eof() is a bad idea, and (if the reading was fixed) you have a buffer overflow if there are more than 20 pairs of items in your file.
To solve the I/O problem you could write it this way:
for (int i = 0; i < 20; ++i)
{
getline(infile , name[i]);
infile >> scores[i];
infile.ignore(SIZE_MAX, '\n');
if ( !infile )
break;
}
The ignore
line here means that after reading the number, it will consume the remainder of that line.
When the loop finishes, i
will contain the number of pairs that successfully read. The condition to break
out of the loop if input fails is important.
Upvotes: 0
Reputation: 8333
The problem is with getline
after using >>
.
To solve it you can add this method:
istream& eatwhites(istream& stream)
{
// to define white spaces manually:
//const string skip=" \t\r\n";
//while(string::npos != skip.find(stream.peek())){
// stream.ignore();
//}
//or just use isspace:
while(isspace(stream.peek())){
stream.ignore();
}
return stream;
}
and write each getline
like this:
string name;
getline( eatwhites(infile), name);
and also with cin
:
string name;
getline( eatwhites(cin), name);
Upvotes: 0
Reputation: 3796
If you can't use stoi, you can use string streams instead.
std::ifstream infile ("File.txt");
std::string name[20];
int score[20];
for (int i = 0; !infile.eof(); i++){
getline(infile,name[i]);
std::string temp;
getline(infile,temp);
std::stringstream s;
s << temp;
int integertemp;
s >> integertemp; // This will convert string to integer, just like how it is with iostreams.
score[i] = integertemp;
}
Upvotes: 1
Reputation: 66
Instead of "stoi" use "atoi" instead:
scores[i] = atoi(temp.c_str());
http://en.cppreference.com/w/cpp/string/byte/atoi
It's been around since way before C++11.
Upvotes: 1