Difficulty analyzing text from a file - c++

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, e.g., 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, e.g., 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.

Related

calculating a sum with two variables from user created output file

I'm trying to figure out how exactly I'd use my output text file I created to be used to calculate the sums of both variables. My output text file is saving the information correctly, but I get 0 and 0 for my sums so it's not reading the information I think. Also, does the information I enter into the arrays only save into the text file? I need it only being saved into the text file so that the sum calculations are only receiving information from the text file
#include <iostream>
#include <string>
#include<iomanip>
#include <fstream>
using namespace std;
int main() {
int ItemNumber[2];
float price[2];
int sumnumber = 0;
float sumprice = 0;
string myfile = "c:/Users/rz/Desktop/numbers.txt";
int count = 0;
ofstream outFile;
outFile.open(myfile);
while (count <= 1)
{
cout << "enter a price" << endl;
cin >> price[count];
outFile << price[count] << endl;
cout << "enter a item number" << endl;
cin >> ItemNumber[count];
outFile << ItemNumber[count] << endl;
count++;
}
outFile.close();
fstream inFile;
inFile.open(myfile);
while (count <= 1)
{
sumprice = sumprice + price[count];
sumnumber = sumnumber + ItemNumber[count];
}
cout << sumnumber << endl;
cout << sumprice << endl;
system("pause");
return 0;
}
At the end of the first loop:
int count = 0;
while (count <= 1) { ... count++ ... }
the variable count will be set to 2.
Then, when you start the second loop:
while (count <= 1) ...
the condition is already false, hence the body of the loop will never be executed.
In order for this to work, you would have to reset count back to zero so that it runs through the items again. Or, better yet, leave count alone (since it indicates how many items were processed) and use another variable to got through them:
for (int i = 0; i < count; ++i) { ... use i rather than count ... }

Pick a number from two columns and calculate

A given file contains pairs of <two-digit number, amount>. Then take a toss-up two-digit number (called X), and compute the win/loss amount. The win/loss rule is if the input number matches X, then it’s a win and the winning total is (amount * 70); otherwise, it’s a loss of (-amount).
For example: [ticket.txt]
09 10
13 15
25 21
If the toss-up number is 09, the win/loss amount of the ticket is (10 * 70 - 15 - 21)
If the toss-up number is 42, the win/loss amount of the ticket is (-10 - 15 - 21).
This is my beginner project. I stuck at calculating the win amount and lost amount.
This is my problem
#include <iostream>
#include <fstream>
using namespace std;
int line1[100]; // array that can hold 100 numbers for 1st column
int line2[100]; // array that can hold 100 numbers for 2nd column
int main()
{
int winNum, winAmount, lostAmount;
int num = 0; // num start at 0
ifstream inFile;
inFile.open("Ticket.txt"); //open File
if (inFile.fail())
{
cout << "Fail to open the file" << endl;
return 1;
}
cout << "Numbers from File: " << endl;
while (!inFile.eof()) // read File to end of file
{
inFile >> line1[num]; // read first column, the first column is the number that user choosing
inFile >> line2[num]; // read second column, the second column is the amount of money that user paying
cout << "\n" << line1[num] << "\t" << line2[num];
++num;
}
inFile.close();
cout << endl;
cout << "Enter the toss-up number: "; // enter the win number
cin >> winNum;
if (line1[num] == winNum)
{
winAmount = line2[num] * 70; // number user choose = win number, winAmount = winAmount * 70 - lostAmount
cout << winAmount;
}
else
{
lostAmount =- line2[num]; //number user choose != win number, the amount will be -lost amounts
cout << lostAmount;
}
cout << endl << endl;
system("pause");
return 0;
}
You can see result at the end of the code
#include <iostream>
#include <fstream>
using namespace std;
int line1[100]; // array that can hold 100 numbers for 1st column
int line2[100]; // array that can hold 100 numbers for 2nd column
int main()
{
int winNum, winAmount = 0, lostAmount = 0, result = 0;
int num = 0; // num start at 0
ifstream inFile;
ifstream inFile2;
int rowNumber = 0;
string line;
inFile.open("Ticket.txt"); //open File
inFile2.open("Ticket.txt");
if (inFile.fail())
{
cout << "Fail to open the file" << endl;
return 1;
}
while (getline(inFile2, line))
++rowNumber;
cout << "Number of lines in text file: " << rowNumber << "\n";
int myArray[rowNumber][2];
for(int i = 0; i < rowNumber; i++)
for(int j = 0; j < 2; j++)
inFile >> myArray[i][j];
cout << "Numbers from File: " << endl;
for(int i = 0; i < rowNumber; i++)
{
for(int j = 0; j < 2; j++)
{
cout << myArray[i][j] << " ";
}
cout << "\n";
}
cout << endl;
cout << "Enter the toss-up number: "; // enter the win number
cin >> winNum;
for(int i = 0; i< rowNumber; i++)
{
if (myArray[i][0] == winNum)
{
winAmount = myArray[i][1] * 70; // number user choose = win number, winAmount = winAmount * 70 - lostAmount
}
else
{
lostAmount = lostAmount + myArray[i][1]; //number user choose != win number, the amount will be -lost amounts
}
}
result = winAmount - lostAmount;
cout << result;
cout << endl << endl;
system("pause");
return 0;
}
When you test line1[num] == winNum (and all the operations carried out after that) you're using the value of num that you modified with ++num;, this means you're working with empty or not meaningful values for both line1 and line2. For example, if the 3 rows of values showed in your "ticket.txt" are used, they are stored in postions 0, 1 and 2 of the arrays, while the num has a value of 4 at the end.
If I understood what you are trying to achieve, you should put the if-else statement in a for loop that goes from 0 to num, and then every operation on line1 and line2 should be done with the looping variable as an index.
Also, move the cout just after the loop if you want only total amounts to be displayed.

Exercise: for cycle and array

I have to write a program that allows to calculate the arithmetic average of an arbitrary numbers of values (chosen by the user)
It will outputs:
Number: 34
Number: 36
Number: 44
Number: //and I choose to stop input pressing
//Outputs:
It was inserted 3 numbers and the avarage is: 38
Of course i've forgot to post what i've done:
for (int x = 0; x < 50; x++){
cout << "Number: ";
cin >> number[x];
cout << "You have inserted the " << x << " element of the array;" << endl;
sum += number[x];
avarage = sum / number[x];
nEelementi = number[x];}
so I run the program, input some numbers, press something like ctrl+d or trying to add something to the code.. but it only goes from the first to the last element of the array with no values, becouse not entered, of course.. and then print absurd avarage and sum.
I know I don't need an array to do this but it's required from the exercise.. also the exercise only request to use for or while loop and arrays.
What I need is a way to stop the input and calculate the sum and avarage of only what I wrote.
edit1.
I've tried to dived by n writing for(x = 0; x < n, x++) because it made sense to me, but i think it "thinks" n, wrote like this, infinite, because the results is 0 (because the limit of a number divided by infinite is 0).. so i've started becoming mad.
Now i've started thinking that it would be easier to use while loop! and wrote
#include <iostream>
using namespace std;
int main() {
int num[50];
double sum = 0;
double average = 0;
int cont;
int end = 0;
while (cont < 50) {
cout << "num: ";
cin >> num[cont];
sum += num[cont];
cont++;
cout << "Want to continue 0 = sì, 1 = no";
cin >> end;
if (end == 1) {break;}
}
average = sum / cont;
cout << "You have insert " << cont << " elements" << endl;
cout << "LThe sum is: " << sum << endl;
cout << "The avarage is: " << average << endl;
return 0;
}
BUT still doesn't work. My professor says you should be able to stop input number by pressing ctrl+d so I'm not doing good.
Sorry for late answer but i have also to translate the code.. hope all translation is good:)
edit2.
#include <iostream>
int main() {
int sum = 0;
int num;
while ( std::cin ) {
std::cout << "Number: ";
std::cin >> num;
}
if ( std::cin >> num ) {
sum += num;
num++;
}
else {
std::cin.clear();
std::cout << "Input interrupted" << std::endl;
}
std::cout << "Sum is " << sum << std::endl;
std::cout << "You have entered " << num << " numbers" << std::endl;
return 0;
}
I love this new code, very simple and understandable to me, but I was not able to add sum operation, it only outputs 0! (leaving out average)
And also I was not able to determinate, and display, how many numbers I've entered. The last row of the code is just an example of what I want to do..
edit3.
Finally I made it.
#include <iostream>
using namespace std;
int main(){
double numero;
int index = 0;
double somma = 0.;
cout << "Inserire un numero: ";
while( cin )
{
if ( cin >> numero )
{
somma = somma + numero;
index++;
cout << "Inserire un numero: ";
}
else
{
cout << "Input interrotto" << endl;
}
}
cout << "Sono stati inseriti " << index << " numeri e la lora media è:
<< somma / index << endl;
return 0;
}
Thanks so much!
P.S. To the end, I don't need to use an array, it's just simple
There are a few problems here. One is that if the stream errors due to being closed or bad input, you don't recover and you just charge through your loop.
So first, make the loop terminate early if necessary. I'm also going to convert it to a while loop in preparation for the next part.
int x = 0;
while( std::cin && x < 50 )
{
std::cin >> number[x++];
}
Now it terminates early if the stream errors. But what if the user typed in "hello"? You could ignore it and continue like this:
if( std::cin >> number[x] )
{
x++;
}
else
{
std::cin.clear();
}
Notice that I didn't compute the sum or anything inside the loop. There's no need, since you are already putting them in an array. You can just do it after the loop. Here, I'm using std::accumulate
double sum = std::accumulate( number, number + x, 0.0 );
double average = 0.0;
if( x > 0 ) average = sum / x;
Now, you have also said you want an arbitrary number of values. Your original code allowed up to 50. Instead of storing them, you can instead just compute on the fly and discard the values.
double sum = 0.0;
int count = 0;
while( std::cin )
{
double value;
if( std::cin >> value )
{
sum += value;
count++;
}
else
{
std::cin.clear();
}
}
double average = 0.0;
if( count > 0 ) average = sum / count;
If you still want to store the values along the way, you can use a vector.
std::vector<double> numbers;
//...
numbers.push_back( value );
And if you want the user to choose the number of values:
std::cout << "Enter number of values: " << std::flush;
std::size_t max_count = 0;
std::cin >> max_count;
std::vector<double> numbers;
numbers.reserve( max_count );
while( std::cin && numbers.size() < max_count )
{
// ...
}

c++ program stop working with atof()

This is my first program on C++. I successfully build it. When I run it, Windows keep giving me program is stop working, the same result that I try to run it with eclipse.
Here is my code:
#include <iostream>
#include <cmath>
#include <stdlib.h>
#include <vector>
using namespace std;
int main(){
string input;
vector<double> value;
int count = 0;
while(input != "#") {
cout << "Enter value " << count + 1 << "\n";
cin >> input;
cout << input;
if (input != "#") {
value[count] = atof(input.c_str());
}
count++;
}
cout << count;
double sum = 0;
for (int i = 0; i < count; i++) {
sum += value[i];
}
double ave = sum/count;
double dev = 0;
for (int i = 0; i < count; i++) {
dev += pow((value[i] - ave), 2);
}
dev = sqrt(dev / (count - 1));
cout << "\nThe average is " << ave << "\n";
cout << "The standard deviation is" << dev << "\n";
return 0;
}
Anyone has any idea? Thank you.
value[count] = atof(input.c_str());
is a problem since value does not have enough space in it. Use
value.push_back(atof(input.c_str()));
instead.
You also have a logic error in the while loop. count will be incremented even when the input is "#". I recommend changing it to:
while(true) {
cout << "Enter value " << count + 1 << "\n";
cin >> input;
cout << input;
if (input == "#") {
break;
}
value.push_back(atof(input.c_str()));
}
count = value.size();
I tried the code on other's computer. It works great. I think something goes wrong for my compiler.

ifstream runtime error when attempting to save the data into array

I'm having a problem when I try to read the external text file.
The displayed text is correct but when it comes to saving the data into an array, it seems to be wrong.
My input numbers are 4 2 8 0 2 3 0 4 0 5, but after looping through the array, a[i], only '48' appears.
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
void begin ();
void Process (string);
using namespace std;
int main()
{
begin();
system("pause");
return 0;
}
void begin (void){
string file = "data.txt";
Process(file);
}
void Process (string file)
{
int i=0,ch, n = 0, temp, a[50];
ifstream infile;
infile.open(file.c_str());
The error seems to be caused from here.
if(infile.is_open())
{
cout << "File to be read: " << file << endl;
cout << "\n\n";
infile >> temp;
while(!infile.fail())
{
cout << temp << " ";
infile >> temp;
a[i] = temp;
i++;
n++;
}
cout << "\n\n";
cout << "This file has " << n << " numbers. \n\n";
}
else
cout << "The file isn't available! \n\n";
infile.close();
When I try to output the result, only 48 appears.
for (int z = 0; z < i; z++)
{
cout << a[i] << endl;
}
}
I'm new here. Please help. Thanks in advance.
Your display loop is using i instead of z to index into a (this should be a good lesson on why variable naming is important!) Change your display loop to this:
for (int z = 0; z < i; z++)
{
cout << a[z] << endl;
}
There are potentially more issues with your code, but this seems to be what is blocking you. Consider renaming i and a to more meaningful things. The time you will spend typing will always be dwarfed by the time you spend trying to understand what you meant.
Consider this loop
for (int z = 0; z < i; z++)
{
cout << a[i] << endl;
}
You always output one element a[i] instead of a[z]. Moreover element with index i was not assigned. The last assigned element is a[i-1].
Apart from this you do not save the first entered number in the array. You start to save entered data from the second number.
infile >> temp; // <== this value was not assigned to an element of the array
while(!infile.fail())
{
cout << temp << " ";
infile >> temp;
a[i] = temp;
Also this statement inside the loop
infile >> temp;
can result in error. So after that there is no sense to write
a[i] = temp;
because nothing was entered and in fact you will store the previous number in the next element.