简体   繁体   中英

Infinite loop in C++ why?

Im sorry about posting a super long code, but when I run this code all I see is this- Heap size: 1638652 Getting int: Getting int: Getting int: Getting int: Getting int: Heap size: 1638653 and it keeps going in a loop with the heapsize being incremented by one.

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <exception>

#ifndef WX_REPORT_H
#define WX_REPORT_H


#include <string>
#include <sstream>
using std::string;
using std::stringstream;

typedef struct WX_REPORT

{
    string unitType;
    string stationName;
    string time;
    string gpsLoc;
    int pressure;
    int windSpeed;
    int temperature;
    int humidity;
    int windDirection;

    string toString()
    {
        stringstream str;
        str << stationName << ": " << time << "\t" << gpsLoc << "\n";
        str << pressure << "\n" << windSpeed << "\n" << temperature << "\n";
        str << humidity << "\n" << windDirection;
        return str.str();
    }
}
WXReport;

#endif
/*
 * Reports must be in the following format:
 * M or I // Metric or imperial units
 */
using namespace std;

vector<WXReport*> heap;

bool compTime(const WXReport* a, const WXReport* b) {
    if(a->time < b->time) { // timing
        return false;
    } else {
        return true; // commands to return true
    }
}

void heapAdd(WXReport* wx) {
    heap.push_back(wx);
    push_heap(heap.begin(), heap.end());
}

WXReport* heapPop() { // header popup
    pop_heap(heap.begin(), heap.end());
    WXReport* rep = heap.back();
    heap.pop_back();
    return rep;
}

void getInt(istream &input, int &i) {
    string temp;
    input>>temp;
    cout<<"Getting int: "<<temp<<endl;
    i = atoi(temp.c_str());
}

void readInFile(string filename) {
    ifstream input(filename);
    WXReport *report;
    while(!input.eof()) {
        report = new WXReport();
        getline(input, report->unitType);
        getline(input, report->stationName);
        getline(input, report->time);
        getline(input, report->gpsLoc);
        getInt(input, report->pressure);
        getInt(input, report->windSpeed);
        getInt(input, report->temperature);
        getInt(input, report->humidity);
        getInt(input, report->windDirection);
        heapAdd(report);
        cout<<"Heap size: "<<heap.size()<<endl;
    }
}

int menu() {
    cout<<"\n\nPlease select one: "<<endl;
    cout<<"1) Read in another file"<<endl;
    cout<<"2) Display the fastest wind speed"<<endl;
    cout<<"3) Display weather stations by name"<<endl;
    cout<<"4) Display all weather reports"<<endl;
    cout<<"5) Remove a weather report"<<endl;
    cout<<"6) Write weather reports to file"<<endl;
    cout<<"0) Exit"<<endl;
    int choice;
    cin>>choice;
    return choice;
}

void printAllReports() {
    cout<<"Printing all reports"<<endl;
    for(WXReport* rep: heap) {
        cout<<rep->toString()<<endl;
    }
    cout<<"Done printing reports"<<endl;
}

int main(int argc, char* argv[]) {
    string filename = "report.txt";
    readInFile(filename);

    int choice = menu();
    while(choice != 0) {
        switch(choice) {
            case 1:
                cout<<"What file would you like to read in?"<<endl;
                cin>>filename;
                readInFile(filename);
                break;
            case 2:
                cout<<"Has not been implemented"<<endl;
                break;
            case 3:
                cout<<"Has not been implemented"<<endl;
                break;
            case 4:
                printAllReports();
                break;
            case 5:
                cout<<"Has not been implemented"<<endl;
                break;
            case 6:
                cout<<"Has not been implemented"<<endl;
                break;
            default:
                cout<<"Invalid choice, please try again."<<endl;
        }
        choice = menu();
    }
    cout<<"Thank you!"<<endl;

    return 0;
}

Important part. If you read nothing else, read this: Always check the error codes and return values.

After ifstream input(filename); you have no idea if the file opened. Testing with input.is_open() gets past that.

If the file isn't open, all those calls to getline fail as does eof() . File not open, can't read end of file and can't exit loop. Even if the the file is open, if you don't check the output of getline, how do you know you read a line?

One of the fun parts of streams is if you test the stream, it tells you if it is in a bad state, so you can write code that looks like

if (getline(...) && getline(...) && ...)

So you don't have to make a massive block of if-else-if or a sea of nested ifs. First bad read and you are out.

The problem with if eof() is covered in the comments to the question. The basic is you don't know if you got the end of the file until you start reading. Also, what happen if you hit the end of the file in the middle of a bunch of reads?

So read a line. If it's good, read the next line, etc... until done.

getInt isn't necessary.

int val;
input >> val;

loads an integer into val, if the stream can be parsed into an int. If it can't, input is marked bad and you can check why. Could be unparsable. Could be end of file.

int val;
if (input >> val)
{
    //do stuff
} 
else
{
    //no int here. Do other stuff
}

Just like above, you can chain the instructions and get

if (input >> val >> anotherval >> ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM