简体   繁体   中英

Difficulty analyzing text from a file

I'm running into a rather amusing error with my output on this lab and I was wondering if any of you might be able to hint at where my problem lies.

The goal is find the high, low, average, sum of the record, and output original record. I started with a rather basic program to solve for one record and when I achieved this I expanded the program to work with the entire text file. Initially the program would correctly output:

346 130 982 90 656 117 595 High# Low# Sum# Average#

When I expanded it to work for the entire record my output stopped working how I had wanted it to.

0 0 0 0 0 0 0 High: 0 Low: 0 Sum: 0 Average: 0 0 0 0 0 0 0 0 High: 0 Low: 0 Sum: 0 Average: 0 etc...

I cant quite figure out why my ifstream just completely stopped bothering to input the values from file.

I'll go take a walk and take another crack at it. If that doesn't work I'll be back here to check for any responses =)

Thank you!

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
    int num;
    int high = 0;
    int low = 1000;
    double average = 0;
    double sum = 0;
    int numcount = 0;
    int lines = 1;
    char endoline;
    ifstream inData;
    ofstream outData;

    inData.open("c:\\Users\\Nikko\\Desktop\\record5ain.txt");
    outData.open("c:\\Users\\Nikko\\Desktop\\record5aout.txt");
    if(!inData) //Reminds me to change path names when working on different computers.
    {
        cout << "Could not open file, program will exit" << endl;
        exit(1);
    }
    while(inData.get(endoline))
    {
        if(endoline == '\n')
            lines++;
    }

    for(int A = 0; A < lines; A++)
    {
        for(int B = 0; B < 7; B++)
        {
            while(inData >> num)
            inData >> num;
            numcount++;
            sum += num;
            if(num < low)
                low = num;
            if(num > high)
                high = num;
            average = sum / numcount;
            outData << num << '\t';
        }
        outData << "High: " << high << " " << "Low: " << low << " " << "Sum: " << sum << " " << "Average: " << average << endl; 
    }   

inData.close();
outData.close();
return(0);
}

In the inner loop you read until the stream enters failure-mode, eg, because an incorrect format was received or the stream reached its end. Once the stream entered failure-mode it will stay in this mode until the error flag is used, eg, using inData.clear() . I don't know how your input looks but assuming it is a file consisting entirely of numbers, it will just read the entire file. If you want to break out of reading earlier, you need to do something about. For example, you could use a manipulator to skip over whitespace and set the stream into a failure state when reaching a newline:

std::istream& skip(std::istream& in) {
    std::istream::sentry cerberos(in, false);
    if (in) {
        while (std::isspace(in.peek()) {
            if (in.get() == '\n') {
                std::in.setstate(std::ios_base::failbit);
            }
        }
    }
}

... later, when reading integers use this:

int value(0);
while (in >> skip >> value) {
    // ...
}
// ... 
if (!in.eof()) {
    in.clear();
}

When skip encounters a newline, the stream is set into failure-mode as a record (line) was read. After processing the line, the stream state is cleared unless the failure was due to also reaching EOF which would set the std::ios_base::eofbit which is tested using in.eof() .

I think you have too many cycles :)

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int num;
int high = 0;
int low = 1000;
double average = 0;
double sum = 0;
int numcount = 0;
int lines = 1;
char endoline;

ifstream inData;
ofstream outData;

inData.open("c:\\Users\\Nikko\\Desktop\\record5ain.txt");
outData.open("c:\\Users\\Nikko\\Desktop\\record5aout.txt");
if(!inData) //Reminds me to change path names when working on different computers.
{
    cout << "Could not open file, program will exit" << endl;
    exit(1);
}
while(inData.get(endoline))
{
    if(endoline == '\n')
        lines++;

    sum = 0;
    average = 0.;
    high  = 0;
    low = 1000;
    //you have to reinitialize these values for every row
    while(inData >> num) 
    {
        numcount++;
        sum += num;
        if(num < low)
            low = num;
        if(num > high)
            high = num;
        average = sum / numcount;
        outData << num << '\t';
    }
    outData << "High: " << high << " " << "Low: " << low << " " << "Sum: " << sum << " " << "Average: " << average << endl; 
}


inData.close();
outData.close();
return(0);
}

Thank you both for taking the time to help me out with this. I borrowed bits from both of your responses.

After my first while loop I added in inData.clear(); & inData.seekg(0);. Adding these stopped my inData >> num from being filled with -858993460.

I also removed the pesky while(inData >> num) and simply replaced it with inData >> num;

Lastly, I set the variables that would need to be reinitialized to 0 inside the first for loop.

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