C++ Reading multiple integers from a text file - c++

I'm a beginning C++ student and am having difficulty in getting my code to read multiple integers from a text file.
My task is to take pre existing code (the code I posted below) and modify it so instead of taking a user's input, it reads from a text file.
The main issue i'm having lies in the void getNumber function. It originally was just a simple cin statement that read 20 numbers input by the user, carried them into the main function, processed them in another function, then prints the results in the last one.
I have modified the code to read the text file successfully, however, it only reads the first value of the text file (ex text file reads: 1 2 3 4 ... 20) and the output reads: 1 1 1 1 1...
I've been looking up solutions for hours, unfortunately, a lot of the responses call for things I am not familiar with. It seems I will need to establish some type of loop? I'm unsure.
Thank you!
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
const int N = 20;
//Function prototypes
void initialize(int& zeroCount, int& oddCount, int& evenCount);
void getNumber(int& num);
void classifyNumber(int num, int& zeroCount, int& oddCount,
int& evenCount);
void printResults(int zeroCount, int oddCount, int evenCount);
int main ()
{
//Variable declaration
int counter; //loop control variable
int number; //variable to store the new number
int zeros; //variable to store the number of zeros
int odds; //variable to store the number of odd integers
int evens; //variable to store the number of even integers
initialize(zeros, odds, evens); //Step 1
cout << "Please enter " << N << " integers."
<< endl; //Step 2
cout << "The numbers you entered are: "
<< endl;
for (counter = 1; counter <= N; counter++) //Step 3
{
getNumber(number); //Step 3a
cout << number << " "; //Step 3b
classifyNumber(number, zeros, odds, evens); //Step 3c
}// end for loop
cout << endl;
printResults(zeros, odds, evens); //Step 4
return 0;
}
void initialize(int& zeroCount, int& oddCount, int& evenCount)
{
zeroCount = 0;
oddCount = 0;
evenCount = 0;
}
void getNumber(int& num)
{
ifstream inData;
inData.open("inputfile.txt");
inData >> num;
}
void classifyNumber(int num, int& zeroCount, int& oddCount,
int& evenCount)
{
switch (num % 2)
{
case 0:
evenCount++;
if (num == 0)
zeroCount++;
break;
case 1:
case -1:
oddCount++;
} //end switch
} //end classifyNumber
void printResults(int zeroCount, int oddCount, int evenCount)
{
ofstream outData;
outData.open("outputfile.txt.");
outData << "There are " << evenCount << " evens, "
<< "which includes " << zeroCount << " zeros"
<< endl;
outData << "The number of odd numbers is: " << oddCount
<< endl;
outData.close();
} //end printResults

The problem is that in the getNumber function you open the file every time it's called. That makes it start the reading from the beginning every time.

What happens is that you open the file every time inside of the getNumber function.
In doing so, you always start reading the file from the beginning. What you'd want to do is to read each time the next integer and not the same one. To do this you could open the file from the main function and pass the ifstream to the getNumber function.
int main ()
{
...
ifstream inpStream;
inpStream.open("inputfile.txt");
for (counter = 1; counter <= N; counter++) //Step 3
{
getNumber(number, inpStream); //Step 3a
cout << number << " "; //Step 3b
classifyNumber(number, zeros, odds, evens); //Step 3c
}// end for loop
return 0;
}
void getNumber(int& num, istream& inpStream)
{
inpStream >> num;
}
Notice that this way you can define inpStream to be cin and it will work too. That is because the getNumber function gets a reference to an istream (which cin is).

Related

Can't solve floating point exception in c++

This is my code.
#include <iostream>
using namespace std;
typedef struct
{
int polski;
int wf;
int matma;
}oceny;
int funkcja_liczaca(int suma, int ile_liczb, int ktory_przedmiot, oceny &temporary);
int main()
{
int suma = 0;
int temp[3];
int ile_liczb_zostalo_wprowadzonych = 0;
oceny database;
string teksty[3] = {"polski: ", "wf: ", "matma: "};
for (int i=0; i!=3; i++)
{
cout << teksty[i] << endl;
while(temp[i]!=0)
{
cin >> temp[i];
if(cin.good()) //floating point exception here. the code don't even step into this one.
{
{
suma = temp[i] + suma;
ile_liczb_zostalo_wprowadzonych++;
if(temp[i]==0){ile_liczb_zostalo_wprowadzonych--;}
}
}else cout << "error";
};
funkcja_liczaca(suma, ile_liczb_zostalo_wprowadzonych, i, database);
suma = 0;
ile_liczb_zostalo_wprowadzonych = 0;
}
cout << "output of struct members in main() \n";
cout << database.polski << endl;
cout << database.wf << endl;
cout << database.matma << endl;
return 0;
}
int funkcja_liczaca(int suma, int ile_liczb, int ktory_przedmiot, oceny &temporary)
{
if(ktory_przedmiot==0){temporary.polski=suma/ile_liczb;cout << temporary.polski << endl;}
if(ktory_przedmiot==1){temporary.wf=suma/ile_liczb;cout << temporary.wf << endl;}
if(ktory_przedmiot==2){temporary.matma=suma/ile_liczb;cout << temporary.matma << endl;}
}
It counts arithmetic average of inputed numbers untill user input 0 which ends loop. then the arithmetic average of thoose numbers is counted in the funkcja_liczaca() and it's saved into the members of struct oceny.
everything works fine but i want to implement something like "stream" check while inputing from keyboard to prevent inputing bad variables into integer type variable.
so inputing 'g' into temp[i] is causing floating point exception. the question is why? cin.good() and cin.fail() is not working.
When you want to deal with errors in the input stream, it's better to read the input line by line as a string and then attempt to extract your data from the string. If extraction of the data from the string is successful, proceed to process the data. Otherwise, attempt to read the next line of text. Here's the core logic for that.
while ( true )
{
cout << teksty[i] << endl;
std::string line;
if ( !getline(cin, line) )
{
// Problem reading a line of text.
// Exit.
exit(EXIT_FAILURE);
}
// Construct a istringstream object to extract the data.
std::istringstream istr(line);
if ( istr >> temp[i] )
{
// Extracting the number was successful.
// Add any additional checks as necessary.
// Break out of the while loop.
break.
}
// Bad input. Continue to the next iteration of the loop
// and read the next line of text.
}

Processing values in each text file one at a time c++

I'm trying to processes values from two text files.One holds a set of chars and the other holds a set of integers.each in their respective places in the text file will amount to one test case.For example the first value that is read in each text file is 1 test case.The values are then used to be checked for variability then Which will then be used as variables through out my code.then in the end prints out a double. The issue is I do not know how to reach that second iteration of test cases. All my code does is read the first values of each text file and prints out the double i need but for only the first test case. As i was typing this out i thought of maybe deleting the values once they are done being used then rerunning the program by having my main in a for loop? suggestions?
#include <iostream>
#include <fstream>
using namespace std;
//function prototypes
char getPackage();
bool vaildPackage(char);
int getHours();
bool validHours(int);
double calculatePakg_A(int);
double calculatePakg_B(int);
double calculatePakg_C(int);
void showBill(double);
int main()
{
char Package = getPackage();
int Hours = getHours();
double bill;
switch (Package)
{
case 'A':bill = calculatePakg_A(Hours);
cout << bill << endl;
break;
case 'B':bill = calculatePakg_B(Hours);
cout << bill << endl;
break;
case 'C':bill = calculatePakg_C(Hours);
cout << bill << endl;
break;
case 'a':bill = calculatePakg_A(Hours);
cout << bill << endl;
break;
case 'b':bill = calculatePakg_B(Hours);
cout << bill << endl;
break;
case 'c':bill = calculatePakg_C(Hours);
cout << bill << endl;
break;
default: cout << "you did not enter a valid Service Plan. \n";
break;
}
return 0;
}
char getPackage()
{
ifstream inputFile;
char a;
inputFile.open("Packages.txt");
do
{
inputFile >> a;
} while (! vaildPackage(a));
return a;
}
bool vaildPackage(char a)
{
return a == 'a' || a == 'A'|| a == 'B' || a == 'b'|| a == 'C' || a == 'c';
}
int getHours()
{
ifstream inFile;
int n;
inFile.open("Hours.txt");
do
{
inFile >> n;
} while (! validHours(n));
return n;
}
bool validHours(int n)
{
return n>=0 && n<= 720;
}
double calculatePakg_A(int hrs)
{
if(hrs <=50)
{
return 15.00;
}
else
{
return (hrs-50) * 2.00 + 15;
}
}
double calculatePakg_B(int hrs)
{
if(hrs <=100)
{
return 20.00;
}
else
{
return (hrs-100) * 1.50 + 20.00;
}
}
double calculatePakg_C(int hrs)
{
if(hrs <=150)
{
return 25.00;
}
else
{
return (hrs-150) * 1.00 + 25.00;
}
}
Package.txt
A a B b C c e c
Hours.txt
50 51 100 101 149 251 750 722
As I'm sure you know, you can read multiple fields from a stream:
ifstream inputFile;
char a;
inputFile.open("Packages.txt");
inputFile >> a;
cout << a << endl;
inputFile >> a;
cout << a << endl;
The reason your code doesn't work is that when control returns from getPackage(), the variable inputFile is deleted, so every time you call that function, it opens the file anew and starts reading from the beginning.
One solution is to make the input stream a static variable, so that it will not be deleted, but will maintain its state from one call to the next:
char getPackage()
{
static ifstream inputFile("Packages.txt");
char a;
inputFile >> a;
return a;
}
I think the only issue here is this.
In the function getPackage()
inputFile.open("Packages.txt");
This opens the file every time you call this function
Due to this, this function is reading the first entry (only) every time.
The same issue with getHours function.
One way out is you can read all entries from the file once into a data structure, say vector and iterate through the vector in the main function.
Another way is open the file(s) in main function and introduce a loop in main that calls these functions. Every time they are called, they would return the next entry from the file. This requires passing the opened file ifstream & as an argument to functions getHours and getPackage

Figuring out why Word Counter program output is 0 or 1

I need to figure out a bug with my program. When I type Hello World I am, it should count the number of spaces, but I keep getting 0 or 1. Below is my full program:
#include "windows.h"
#include <iostream>
#include <cctype>
using namespace std;
//Global declarations.
//Function prototypes.
void pause();
void numWords(string&);
int numWords(char []);
int main()
{
string userVal;
numWords(userVal);
char *conStr= new char[userVal.length()];
strcpy(conStr, userVal.c_str()); //String converted to a C-string.
int fin= numWords(conStr);
cout<< "The number of words in the sentence is "<< fin<< "."<< endl;
delete[] conStr;
conStr= 0;
pause();
return 0;
}
/***************************************FUNCTIONS**********************************************************************/
/*1st function to pause the program.*/
void pause()
{
cin.sync();
cin.ignore();
}
/*2nd function to ask the user for input. OP*/
void numWords(string &len)
{
cout << "Please enter a sentence and I will tell you how many words it has: " << endl;
cin >> len;
}
/*3rd function to count the number of total spaces in the sentence.*/
int numWords(char usStr[])
{
int wrdCount= 0,
chrCount= 0,
index= 0;
while(usStr[index]!= '\0')
{
if(isspace(usStr[index]))
{
if(chrCount)
{
wrdCount++;
chrCount= 0;
}
}
else
chrCount++;
index++;
}
if(chrCount)
wrdCount++;
return wrdCount;
}
Can anyone please explain why it doesn't count the spaces, or if I need another loop mechanism to make this work? Thank you.
CoryKramer's suggestion was correct. cin will stop after the first whitespace. If you want to read a whole line, you use getline. I've made changes to your code to show this as well as renamed the function you use to get the sentence from the user. Also, you don't have to convert to a c-style string for this to work, a string works just fine.
//Function prototypes.
void pause();
void getSentence(string&);
int numWords(string&);
int main()
{
string userVal;
getSentence(userVal);
int fin = numWords(userVal);
cout << "The number of words in the sentence is " << fin << "." << endl;
pause();
return 0;
}
void getSentence(string &len)
{
cout << "Please enter a sentence and I will tell you how many words it has: " << endl;
getline(cin, len);
}
int numWords(string& usStr)
{
int wrdCount = 0,
chrCount = 0,
index = 0;
while(index < usStr.length())
{
...
}
if(chrCount)
wrdCount++;
return wrdCount;
}
You also probably want to #include <string>

My search function in C++ is pulling up all the answers and not a single one

I'm really confused. I have to make this lab for a class and I can't seem to have the search only display one result but all of the months of the year. I also can't seem to figure out why its not displaying the TotalRainfall when I input 0 into the month of the year.
Thank you.
#include <iostream>
#include <fstream>
const int MaxSize = 12; //How many weather lines will be available.
using namespace std;
struct WeatherInformation
{
int Month; //Months of the year
float TotalMonthsRainfall; //Total amount of rainfall
float HighTemp; //The Highest temperature of the month.
float LowTemp; //The Lowest temperature of the month.
float AverageTemp; //The Average temperature of the month.
};
WeatherInformation WeatherArray[MaxSize]; //Declaring a month array of MaxSize
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[]);
void WeatherMonthSearch (WeatherInformation WeatherArray[]);
int main()
{
float TotalRainfall = 0;
int count = 1; //Counts how many times the for loop goes.
int MonthOfWeather; //User input of the month.
char ProgramRedo; //User input if they want to reuse the program.
char exit_char; //User input to exit the program.
ifstream MyinFile; //Variable that uses file.
ReadFile (MyinFile, WeatherArray); //Call ReadFile Function
WeatherMonthSearch (WeatherArray); //Call WeatherMonthSearch Function
MyinFile.close(); //Closes file.
}
//Brett Holmes
//4/30/2013
//PreCondition:You need a file labeled weather.dat
//PostCondition: It puts the file variables into an array.
void ReadFile(ifstream& MyinFile, WeatherInformation WeatherArray[])
{
float TotalRainfall = 0;
char exit_char;
int count = 0;
int Month = 0;
cout << "Your Weather Machine" << endl << endl;
MyinFile.open("weather.dat");
if (!MyinFile)
{ //no
cout << "Can't open input file." << endl; //Tests the right file.
char exit_char; //End Program
cout << "Press any key to exit" << endl;
cin >> exit_char;
}
for(count = 1; count < MaxSize; count++) //Puts the file variables in the array.
{
WeatherArray[count].Month = WeatherArray[count].Month + 1;
MyinFile >> WeatherArray[count].TotalMonthsRainfall;
MyinFile >> WeatherArray[count].HighTemp;
MyinFile >> WeatherArray[count].LowTemp;
(WeatherArray[count].AverageTemp = ((WeatherArray[count].HighTemp + WeatherArray[count].LowTemp)/2));
(TotalRainfall = TotalRainfall + WeatherArray[count].TotalMonthsRainfall);
}
}
//Brett Holmes
//4/30/13
//PreCondition:You need to have the months already put into an array in a struct.
//PostCondition:Outputs the rainfall stats the user puts in then asks to run again.
//Outputs a error message if they type in the month wrong.
void WeatherMonthSearch (WeatherInformation WeatherArray[])
{
float TotalRainfall;
int months;
int MonthOfWeather;
char ProgramRedo;
do
{
bool MonthFound = false;
cout << "Please input the number of the Month. Ex. 1=Jan. 2=Feb. etc \n\n";
cin >> MonthOfWeather;
for(int i = 1; i <= MaxSize; i++)
{
months = WeatherArray[i].Month;
if(months == MonthOfWeather ) //Finds the artist and outputs the results
{
cout << "\nTotal Months Rainfall: " << WeatherArray[i].TotalMonthsRainfall << " \n";
cout << "Highest Temperature: " << WeatherArray[i].HighTemp << " \n";
cout << "Lowest Temperature: " << WeatherArray[i].LowTemp << " \n";
cout << "Average Temperature: " << WeatherArray[i].AverageTemp << " \n";
MonthOfWeather = true;
}
}
if(MonthOfWeather == 0)
{
cout << "The total rainfall for the year is: " << TotalRainfall << ".";
}
if(MonthFound == false)
{
cout << "\nMonth Number error. Month not found. Try again.\n\n";
MonthOfWeather = false;
}
cout << "Would you like to look up another month of weather?\n";
cout << "Enter a 'Y' if yes and 'N' if no.\n";
cin >> ProgramRedo;
}while(ProgramRedo == 'Y');
}
Several obvious problems:
Arrays in C++ is 0-based, so your for loop is off-by-one. In your search function, for(int i = 1; i <= MaxSize; i++) should be for(int i = 0; i < MaxSize; i++). Similarly, in your read function, for(count = 1; count < MaxSize; count++) should be for(count = 0; count < MaxSize; count++) (If you want to skip index 0 because you are using it as a signal value, then you should set MaxSize to 13 and have the loop start at 1.)
Why are you assigning a boolean to MonthOfWeather? Do you mean MonthFound?
You read function is not setting the months correctly. WeatherArray[count].Month = WeatherArray[count].Month + 1; should be WeatherArray[count].Month = count; if you are using a 1-based loop or WeatherArray[count].Month = count + 1; if the loop is 0-based.
You calculated your total rainfall in the read function, but the result is stored in a local variable so it's lost when the read is done. Either make TotalRainfall a global variable or do your calculations in your search function.
There are a lot of redundant variable definitions: for example, your weather data array is a global so there is no reason to actually pass it around; exit_char is declared twice in your read function; the first five lines of your main() declared variables that you never used.
Also, your read function does not actually exit the program on failure - it even still attempts to read from the stream and then call your search function! If error-checking is a requirement, you should either have the read function return a boolean and check that the read function succeeded before calling your search function, or simply call std::exit after that cin >> exit_char;.
So, one problem you have is that you have local variables that appear in multiple places, but appears like you expect them to actually contain the same information.
For example, I see three different TotalRainFall. One in main, which is just there, not used for anything, one in ReadFile which is calculated, and one in WeatherMonthSearch, which is not set to anything.
I suspect you want all three of these to actually do something. One way to achieve that would be to remove the local ones in ReadFile and WeatherMonthSearch, and instead pass in the one from main (as a reference into ReadFile).
There's also a few places where you use variables without initializing them. Make it a habit to initialize EVERYTHING and EVERYWHERE!
Enable warnings in your compiler - if you have any form or reasonably new compiler (gcc or MS Visual Studio of recent vintage), it should tell you at least some of these things.

Getting a 2D array from a function that returns an int c++

I have an assignment that simulates a dice game. As part of the program, the user enters the number of dice to roll and the number of times to roll them. If the user rolls 4 dice, the program should sum the 4 values, store the result in an array, then redo the program the number times defined by the user. The main code and the function prototypes were defined by our tutor and cannot be amended. We have to write the function.
In Step 3 of the main, there are two for loops. The inner for loop calls the function in question. A 2D array rollSums[][] is assigned to the result of the function. This array is to be used in another function. I can't figure out how to populate the 2D array correctly from the function. The code and my attempt at the function is below:
#include <iostream>
#include <iomanip>
#include <cstdlib> // needed for functions srand() and rand()
#include <ctime> // needed for function time()
#include <cmath> // needed for sqrt()
using namespace std;
const int MAXNUMTOROLL=10;
const int MAXROLLS=100;
int rollDice(int diceVals[], int numToRoll);
int main()
{
int sum;
int rollSums[MAXNUMTOROLL][MAXROLLS];
int diceVals[MAXROLLS];
double mean[MAXNUMTOROLL], std[MAXNUMTOROLL];
int numToRoll, numRolls;
srand(time(NULL));
// STEP 1: Ask user to input the maximum number of dice to use:
cout << "Please enter the maximum number of dice to use:" << endl;
do
{
cin >> numToRoll;
} while (numToRoll < 0 || numToRoll > MAXNUMTOROLL);
cout << "Please enter the number of rolls:" << endl;
// STEP 2: Ask user to input the number of rolls to carry out:
do
{
cin >> numRolls;
} while (numRolls < 0 || numRolls > MAXROLLS);
// STEP 3: For k=1 to numToRoll, simulated numRolls rolls of the dice
// and store the sum of the numbers rolled in the array rollSums[][]
for (int k=1;k<=numToRoll;k++)
{
for (int i=0;i<numRolls;i++)
{
rollSums[k-1][i] = rollDice(diceVals, k);
}
}
return 0;
}
int rollDice(int diceVals[], int numToRoll) //function simulating throwing of dice
{
int sum=0;
int i=0;
for(i=0;i<numToRoll;i++)
{
diceVals[i]=1+rand()%6;
sum=sum+diceVals[i];
}
return sum;
}
adohertyd, see my comments in the code sample:
#include <iostream>
#include <iomanip>
#include <cstdlib> // needed for functions srand() and rand()
#include <ctime> // needed for function time()
#include <cmath> // needed for sqrt()
using namespace std;
const int MAXNUMTOROLL=10;
const int MAXROLLS=100;
const bool show_debug = true;
int rollDice(int diceVals[], int numToRoll);
int main()
{
int roll_Sums[MAXNUMTOROLL];
int diceVals[MAXROLLS];
//double mean[MAXNUMTOROLL], std[MAXNUMTOROLL];
int numDice, numThrows;
//Initialize random number generator with the current time
srand(time(NULL));
// STEP 1: Ask user to input the maximum number of dice to use:
cout << "Please enter the maximum number of dice to use:" << endl;
// STEP 2: Validate number of dice input
do
{
cin >> numDice;
} while (numDice < 0 || numDice > MAXNUMTOROLL);
//STEP 3: Ask user to input the number of times to throw each dice
cout << "Please enter the number of rolls:" << endl;
// STEP 4: Validate number of throws input
do
{
cin >> numThrows;
} while (numThrows < 0 || numThrows > MAXROLLS);
cout << "\n\nThrowing Dice Now...\n\n";
// STEP 5: Roll the dice
//The loop deals with each dice
for (int diceCount = 0; diceCount < numDice; diceCount++)
{
//The function call deals with all the throws per dice
//Note: roll_Sums array didn't need to be two dimensional,
// also, rollDice gets passed diceVals[] by value and the number of throws to execute
roll_Sums[diceCount] = rollDice(diceVals, numThrows);
//Debug output
if(show_debug)
{
//Since roll_Sums is zero based, add one to the visible index so the user doesn't get confused :P
cout << "Roll Sum for dice #" << diceCount + 1 << ": " << roll_Sums[diceCount] << endl << endl;
}
}
return 0;
}
//rollDice() returns the sum of all the dice rolls it performed
int rollDice(int diceVals[], int numToRoll)
{
int sum=0;
for(int i=0;i<numToRoll;i++)
{
//Get your random dice rolls
diceVals[i]=1+rand()%6;
//Debug output
if(show_debug)
{
cout << "Dice Roll # " << i+1 << ": " << diceVals[i] << endl;
}
//Accumulate your value, e.g. "sum"
sum += diceVals[i];
}
return sum;
}