This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 4 years ago.
Keep getting stuck in an infinite loop dont know where my logic went wrong
used while eof and dont know what else is missing, also break statement didnt do anything but print out my test statement once
void readSetupData(string sfile, string efile, string afile, students
studArray[])
{
ifstream inS(sfile.c_str());
ifstream inA(afile.c_str());
ifstream inE(efile.c_str());
int numStudents = 0;
while (!inS.eof())
{
cout << "BEEP" << endl;
int id;
int examScore;
string name;
inS >> name >> studArray[numStudents].id >>
studArray[numStudents].name;
int examId;
inE >> id >> examId >> examScore;
int studentIndex = findStudent(id, studArray);
int examIndex = findExam(examId,
studArray[studentIndex].examArray);
studArray[studentIndex].examArray[examIndex].pointsScored
=
examScore;
int pointsAvail =
studArray[studentIndex].examArray[examIndex].pointsAvail;
studArray[studentIndex].examArray[examIndex].percentage =
(float)examScore / (float)pointsAvail;
}
while (!inA.eof())
{
int id;
int assignId;
int assignScore;
inA >> id >> assignId >> assignScore;
int studentIndex = findStudent(id, studArray);
int assignIndex = findAssignment(assignId,
studArray[studentIndex].assignArray);
studArray[studentIndex].assignArray[assignIndex].pointsScored
= assignScore;
}
}
the first void function is the problem and the test statement BEEP is repeated when compiled and ran with
./a.out student_info.txt exam_info assignment_info.txt exam_scores.txt assignment_scores grades.out
You are expecting eof to predict the future and assure you that a subsequent read won't encounter an end-of-file. That's just not what it does. Don't use the eof function at all.
You have no handling for any errors except to repeat the operation that failed which, with near certainty, will fail again and repeat the cycle. Instead, check each and every operation to see whether it succeeded or failed. If it fails, don't just keep going because it will just fail again leading to an endless loop.
One of the first things you should do when you don't understand why your code is doing what it's doing is add error checking to every single library call or function call that can possibly error in any conceivable way.
Related
I need some help with a code.
I need to take this information to my c++ code from another file, the last one is just like this:
Human:3137161264 46
This is what I wrote for it, it takes the word "Human" correctly but then it takes random numbers, not the ones written on the file I just wrote:
struct TSpecie {
string id;
int sizeGen;
int numCs; };
__
TSpecie readFile(string file){
TSpecie a;
ifstream in(file);
if (in){
getline(in,a.id,':');
in >> a.sizeGen;
in >> a.numCs;
}
else
cout << "File not found";
return a; }
Hope you can solve it and thanks for your help
3137161264 causes integer overflow leading to Undefined Behaviour.
So unsigned int sizeGen would be enough for this case, but consider long long (unsigned) int sizeGen too.
Edit 1: As pointed out by #nwp in comments to your question, you can also check your stream if any error has occured:
//read something and then
if (!in) {
// error occured during last reading
}
Always test whether input was successful after reading from the stream:
if (std::getline(in, a.id, ':') >> a.sizeGen >> a.NumCs) {
// ...
}
Most likely the input just failed. For example, the first number probably can't be read successful. Also note that std::getline() is an unformatted input function, i.e., it won't skip leading whitespace. For example the newline after the last number read is still in the stream (at least, since your use of std::getline() finishes on a colon, it will only create an odd ID).
So this is the code
#include<iostream>
using namespace std;
int main(){
int a,b;
while(true){
cout<<"Enter the value of a and b ";
cin>>a>>b;
if(a=='|'||b=='|')
break;
else
cout<<"The value of a is "<<a<<"\nThe value of b is "<<b<<endl;
}
}
and the question is Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating '|' is entered.
When i enter input like | it prints infinitely "The value of a is and value of b is ". What is the reason for this?enter code here
std::cin (and I think all streams) by default will set an error flag when you try to read into an invalid data type (e.g. here with trying to read a char into an int variable) and that flag will prevent other std::cin to run until the flag is cleared. To rest the stream, use std::cin.clear() to the reset the error flag and then you have to remove the bad input, either through std::cin.ignore() or read into a string buffer or something, from the stream as it will still be there.
Your istream operator >> as_int is failing and really doing nothing so your loop just keeps going. Either input as chars and convert to ints with checks, or or check the stream for errors.
cin>>a>>b;
if( cin.fail( ) )
break;
istream reading after failure
Additionally: If you had have traced into the istream operator you would have seen why it was not blocking, that it had failed. Always trace when something is wrong...
This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 7 years ago.
I am trying to count the number of words in a file, I know this question has been asked but I have tried some implementations I have seen but I keep getting an error.
The line in the file I am reading is "Super Chill" but when I run the code I get a count 3, where >> gets Super the first time and then Chill twice. I have a couple questions regarding this method:
1) what does While(in) look for? How does it know when to stop?
2) Why is "Chill" getting stored twice with >>?
Here is the code
int countWords(std::istream& in){ // line in file is -> Super Chill
int count = 0;
std::string word;
while (in) {
in >> word;
if (word != "") {
count+= 1;
}
}
return count;
}
while (in) checks if no error has occurred. It's the same as writing while (!in.fail())
After you call in >> word and get the first "Chill", while (in) still is true, until the next call to in >> word. When you hit in >> word again it fails because it's at the end of the file and doesn't write anything to word, but the word variable still has "Chill" in it from the last time, so you count it a second time. Then the while (in) finally fails on the next iteration.
Calling while (in >> word) { ++count; } works because in >> word is actually the function in.operator>>(word) which happens to return an istream&, and an istream has an operator bool method which allows you to use it in a condition instead of writing !in.fail(). Sort of roundabout, I know. Point is, it calls in >> word, then checks if (in) and if it passes then calls ++count; and iterates again. Versus your original technique which counted the previous word even if in >> word failed.
To make this clearer, it might help to know that changing your original code's if statement to if (in) would have also worked, but would be sort of bad code.
As a final conclusion, the entire function could be written as:
int countWords(std::istream& in) {
int count = 0;
for (std::string word; in >> word; ++count) {}
return count;
}
I see you've already gotten one solution to the problem you posted. You might want to consider another possibility though:
int countWords(std::istream& in){
return std::distance(std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>());
}
This doesn't actually eliminate the loop, but it hides it inside of std::distance where it's pretty difficult to mess things up.
int H;
int M;
int SleepH;
int SleepM;
cout << NumActivities[2][0];
cin >> H >> M;
cout << NumActivities[2][1];
cin >> SleepH >> SleepM;
int SubtractM;
int SubtractH;
if (H<=12)
{
int MH=24;
int MM=60;
SubtractH= MH-H;
SubtractM = MM-M;
}
if (SleepM==00)
{
int SleepM= SleepM+60;
int TimeLeftH;
TimeLeftH= SleepH-SubtractH;
int TimeLeftM;
TimeLeftM= SleepM-SubtractM;
int F;
F=TimeLeftM/60;
int DoThisZ;
DoThisZ= TimeLeftH + F;
float Normal = Normal + DoThisZ;
cout<<Normal;
}
}
}
Above is my program. It's unfinished but when doing runs the program keeps ending early right after it outputs NumActivities[2][1] on line 64. I can't find any way to stop this and taking away the loop doesn't change anything.
I expect the program to let me enter the the variables H,M,SleepH and SleepM and then show me the result but it just closes after displaying NumActivities[2][1] without letting me enter the variables.
When the program asks you "What's your bedtime?(In 24 hour format):", if your answer contains colon (:), it takes input for your next question - "How long do you sleep?:" - as well.
This is because in C++, comma-separators are not part of a number, as decimal points aren't for integers, so as soon as the operation finds either the comma or the point, the extraction operation ends, leaving that character as the next to be extracted. Subsequent extraction operations find that character as the first one to be extracted, so they all return.
Enter your first answer as something like "11 30" - space between the numbers, not colon. Then, the program is supposed to take input for your next question as well.
Just to give an advice, you are wasting your iteration numbers 0,1,2,4,5. So, you can simply take away the for loop.
I'm dealing with a problem using eof().
using
string name;
int number, n=0;
while(!in.eof())
{
in >> name >> number;
//part of code that puts into object array
n++;
}
sounds normal to me as it whenever there are no more text in the file.
But what I get is n being 4200317. When I view the array entries, I see the first ones ats the ones in the file and other being 0s.
What could be the problem and how should I solve it? Maybe there's an alternative to this reading problem (having undefined number of lines)
The correct way:
string name;
int number;
int n = 0;
while(in >> name >> number)
{
// The loop will only be entered if the name and number are correctly
// read from the input stream. If either fail then the state of the
// stream is set to bad and then the while loop will not be entered.
// This works because the result of the >> operator is the std::istream
// When an istream is used in a boolean context its is converted into
// a type that can be used in a boolean context using the isgood() to
// check its state. If the state is good it will be converted to an objet
// that can be considered to be true.
//part of code that puts into object array
n++;
}
Why your code fails:
string name;
int number, n=0;
while(!in.eof())
{
// If you are on the last line of the file.
// This will read the last line. BUT it will not read past
// the end of file. So it will read the last line leaving no
// more data but it will NOT set the EOF flag.
// Thus it will reenter the loop one last time
// This last time it will fail to read any data and set the EOF flag
// But you are now in the loop so it will still processes all the
// commands that happen after this.
in >> name >> number;
// To prevent anything bad.
// You must check the state of the stream after using it:
if (!in)
{
break; // or fix as appropriate.
}
// Only do work if the read worked correctly.
n++;
}
in << name << number;
This looks like writing, not reading.
Am I wrong?
int number, n = 0;
You weren't initializing n, and you seem to have a typo.
This probably would be more correct
string name;
int number, n = 0;
while (in >> name && in >> number)
{
n++;
}
The eof is a bad practice.
Note that there is a subtle difference here from your code: your code ended when it encountered an eof or silently looped for infinite time if it found a wrong line (Hello World for example), this code ends when it encounters a non correctly formatted "tuple" of name + number or the file ends (or there are other errors, like disconnecting the disk during the operation :-) ). If you want to check if the file was read correctly, after the while you can check if in.eof() is true. If it's true, then all the file was read correctly.