0

I am trying to allow the user to select which file to open then use either a sentinel value or counter control to get all the values from the selected file. The code I have just outputs:

There are 0 values in the file.

The values in the file are: -1206517578

The average is -inf

Which is not true as there are 10 numbers in each file and they are all less than 9. I have been staring at this and can't figure out what is wrong.

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main() {

    char fileSel;
    double numValues = 0; //# of values in list
    int values; //numbers in list
    double avg = values / numValues;
    int counter = 10;
    const int SENTINAL_VALUE = -9999;

//Which file would you like to open?
    cout << "Which file would you like to open?" << endl;
//1. Counter Controlled
    cout << "1. Counter Controlled" << endl;
//2. Sentinel Controlled
    cout << "2. Sentinel Controlled" << endl;
//Input file
    cin >> fileSel;

//loop file selected
//counter controlled
    while (fileSel == 1){
        //open and check file
        ifstream inFile;
        inFile.open("counter_controlled.txt ");

        if (inFile.fail()) {
            cerr << "Could not open input file" << endl;
            return -1;
        }
        while (numValues <= counter) {
            inFile >> values;
            numValues += 1;
        }

        inFile.close();
    }



    //sentinal
    while ( fileSel == 2) {
        //open and check file
        ifstream inFile;
        inFile.open("sentinel_controlled.txt");

        if (inFile.fail()) {
            cerr << "Could not open input file" << endl;
            return -1;
        }

        //get values until
        while (inFile >> values);
        numValues += 1;
        if (values == SENTINAL_VALUE){
            cout << "There are " << numValues << " values in the file." << endl;
            cout << "The values in the file are: " << values << endl;
            //The average is 4.93.
            cout << "The average is " << avg << endl;
        }
        inFile.close();
    }

    //The values in the file are:
    cout << "There are " << numValues << " values in the file." << endl;
    cout << "The values in the file are: " << values << endl;
    cout << "The average is " << avg << endl;

    return 0;
}
  • Aside. You only need ONE `std::cout` for any continual block of text (not one per-line). Avoid adding `std::endl` after a string-literal, just include the `'\n'` in the literal, e.g. `" values in the file.\n"` See: [C++: “std::endl” vs “\n”](https://stackoverflow.com/questions/213907/c-stdendl-vs-n) So your entire program can use just 3 `std::cout` instead of 9. – David C. Rankin Oct 07 '21 at 05:08
  • Why are you using ` while (fileSel == 1)` instead of `if (fileSel == 1)`? You don't change `fileSel` in the `while` loop, and the only way of exiting the `while` loop is a `return` statement, not a `break`. – jjramsey Oct 07 '21 at 17:03

2 Answers2

1

Starting with just these 3 lines of code:

    double numValues = 0; //# of values in list
    int values; //numbers in list
    double avg = values / numValues;

at this point avg is UNINITIALIZED divided by ZERO, which is not good in multiple ways. I'd think the compiler would have a lot to say about this.

values actually has to be accumulated before its average can be calculated, and values is never accumulated into anything, you just read it in over and over.

...C++ is imperative, not declarative like Excel.

dirck
  • 838
  • 5
  • 10
0

In addition to dirck's observation that you are computing the results before you have the data, there is much more wrong with it.

You are reading the same value over and over, not making a collection of values and not summing the values read.

while (inFile >> values);
has nothing to do with stopping at the sentinel, and the following block of code will test the last value read (only), which is the last value in the file.

JDługosz
  • 5,592
  • 3
  • 24
  • 45