Why won't my code print anything from the screen? (C++) - c++

I am working with a file that contains a set of data:
x values y values
20.00 0
20.02 15
20.04 27
20.06 39
20.08 54
20.10 65
20.12 75
The program is supposed to calculate the area under curve. In this part I am to do so for the first 6 x-y sets. My algorithm for finding the area is the sum of each trapezoid , which for these constraints, should only be 5 trapezoids. The each of each trapezoid is defined by: A = 0.5(base-base_0) * (height + height_0).
This is my code:
int main()
{
ifstream infile;
double AreaCurve = 0.0, NumberTraps = 0.0, height, height_0, base, base_0, AreaTrap;
infile.open("xydata.dat");
cin.ignore(20, '2');
while (NumberTraps < 6)
{
infile >> base_0;
infile >> height_0;
infile >> base;
infile >> height;
AreaTrap = 0.5 * (base - base_0) * (height + height_0);
AreaCurve += AreaTrap;
NumberTraps++;
}
cout << "The area under the curve is: " << setprecision(4) << AreaCurve << endl;
infile.close();
return 0;
}
When I compile the program nothing prints to the screen. I am not sure why this is happening but I believe it may have to do with an error in the line of my code containing the cin.ignore function (I can't edit the data, and I need to skip the line that reads: "x values\t\t y values")

Remove the line cin.ignore(20, '2'); .
This line will make your program wait for user input until they either enter twenty 2s, or enter a different character.
You shouldn't be reading any user input in this program, your input data comes from infile.
You will need to add code to ignore the first line of infile. A simple way to do that is string s; getline(infile, s);
Your program's main loop has a logic bug as well. You are reading in 2 lines at a time and considering that trapezoid, but then you are ignoring the trapezoid just after that one. (So you only count about half of the trapezoids).
Finally you should check for input success before processing that trapezoid:
if ( !infile )
break;

To ignore the first line of the infile stream (regardless of its length) you need:
infile.ignore( numeric_limits<streamsize>::max(), '\n' ) ;
Note, this needs the <limits> header.
You do not need to ignore to the first '2'. For starters the first x value would always have to start with '2', but more usefully std::istream::operator>> (double&); skips white-space including line ends in any case.
There are other issues with this code, such as attempting to read more values that the file contains, an incorrect integration algorithm, and having no error checking for a valid stream. Consider:
infile.ignore( numeric_limits<streamsize>::max(), '\n' ) ;
infile >> base_0;
infile >> height_0;
while( infile.good() )
{
infile >> base;
infile >> height;
if( infile.good() )
{
AreaTrap = 0.5 * (base - base_0) * (height + height_0);
AreaCurve += AreaTrap;
base_0 = base ;
height_0 = height ;
}
}

Related

Problem reading a formatted text file in C++

Officially my first post. I'm sure the Stack is full of answers, but the problem that I need help with is a little bit specific. So here goes nothing...
The Task:
I'm doing a small school project and in one part of my program I need to read the temperature measurements at different locations, all from a single formatted text file. The data inside the file is written as follows:
23/5/2016
Location 1
-7,12,-16,20,18,13,6
9/11/2014
Location 2
−1,3,6,10,8
9/11/2014
Location 3
−5,−2,0,3,1,2,−1,−4
The first row represents the date, second row the location and the third row represents the all the measurements the were taken on that day (degrees Celsius).
The code that I wrote for this part of the program looks something like this:
tok.seekg(0, std::ios::beg);
int i = 0;
double element;
char sign = ',';
while (!tok.eof()) {
vector_measurements.resize(vector_measurements.size() + 1);
tok >> vector_measurements.at(i).day >> sign >> vector_measurements.at(i).month >> sign >> vector_measurements.at(i).year >> std::ws;
std::getline(tok, vector_measurements.at(i).location);
sign = ',';
while (tok && sign == ',') {
tok >> element;
vector_measurements.at(i).measurements.push_back(element);
sign = tok.get();
}
if (!tok.eof() && !tok) {
tok.clear();
break;
}
vector_measurements.at(i).SetAverage();
i++;
}
The code that I'm presenting is linked to a class:
struct Data {
std::string location;
std::vector<int> measurements;
int day, month, year;
double average = 0;
void SetAverage();
int GetMinimalTemperature();
int GetMaximalTemperature();
};
I've already checked and confirmed that the file exists and the stream is opened in the correct mode without any errors; all class methods working as intended. But here's the problem. Later on, after the data is sorted (the part of data that has been successfully read), it fails to correctly print the data on the screen. I get something like:
Location 2
Date: 9/11/2014
Minimal temperature: 0
Maximal temperature: 0
Average temperature: 0
Location 1
Date: 23/5/2016
Minimal temperature: -16
Maximal temperature: 20
Average temperature: 6.57143
; but I expect:
Location 3
----------
Date: 9/11/2014
Minimal temperature: -5
Maximal temperature: 3
Average temperature: -0.75
Location 2
----------
Date: 9/11/2014
Minimal temperature: -1
Maximal temperature: 10
Average temperature: 5.20
Location 1
----------
Date: 23/5/2016
Minimal temperature: -16
Maximal temperature: 20
Average temperature: 6.57143
The Problem:
The order of the locations is good, since I'm sorting from the lowest to the highest average temperature. But no matter the number of locations, the first location is always correct, the second one only has zero's, and every other location isn't even printed on the screen.
What do I need to change in order for my program to read the data properly? Or am I just missing something? Forgive me for any spelling mistakes I made since English isn't my native language. Thank you all in advance, any help is appreciated!
So the issue is there is some garbage in your text file. I do believe these are \0 characters, but I am not sure. They present themselves as ? characters in Atom text editor.
You're quite lucky StackOverflow didn't sanitize them, otherwise, nobody would be able to help you.
After I cleaned up the text file, your code works. You just need to also kill the loop and drop the last item when the file ends, I did it like this. It's not optimal but it works.
while (!tok.eof())
{
vector_measurements.resize(vector_measurements.size() + 1);
Data& currentItem = vector_measurements[i];
tok >> currentItem.day >> sign >> currentItem.month >> sign >> currentItem.year >> std::ws;
// If the file ends, the data is invalid and the last item can be thrown away
if (tok.eof())
{
vector_measurements.pop_back();
break;
}
std::getline(tok, currentItem.location);
sign = ',';
while (tok && sign == ',')
{
tok >> element;
currentItem.measurements.push_back(element);
sign = tok.get();
}
if (!tok.eof() && !tok)
{
tok.clear();
break;
}
currentItem.SetAverage();
i++;
}
Please inspect your file with hex editor and observe the weird characters, then figure out how to get rid of them.

Accumulator and while loops

while(true) {
infile >> studentCode >> test1 >> test2 >> lab >> finalExam;
finalG = finalGrade(test1, test2, lab, finalExam);
gradeSum = gradeSum + finalG;
letterG = letterGrade(finalG);
gradePrinter(); // Prints grades to outfile.
if (infile.eof())
break;
}
In my while loop, the variable finalG does not add to gradeSum at the end of every loop. (gradeSum is initialized to 0 before the while loop). Instead, the value of gradeSum stays at zero and just adds whatever the last number the function finalGrade(test1, test2, lab, finalExam) outputs. For example, if the following numbers are outputted by function:
10
15
30
35
40
The gradeSum will return 40 + 0, which just gives me 40 rather than the sum of the numbers. How can I fix this?
Problem
Your use of the while loop is faulty. You end up processing the grades one more time than is valid.
Let's say you have two lines in your file:
101 18 20 15 48
102 19 20 14 50
After the second line is read, infile.eof() is false. Hence, you continue reading. Reading does not succeed. Yet you process those numbers. You will probably end up processing the last line twice.
A solution
Simplify the while loop by using:
while ( infile >> studentCode >> test1 >> test2 >> lab >> finalExam )
{
finalG = finalGrade(test1, test2, lab, finalExam);
gradeSum = gradeSum + finalG;
letterG = letterGrade(finalG);
gradePrinter();
}
Disclaimer: This won't fix other logic errors in your code.

read line with different length backwards c++

I have a text file that I need to read data from, and these data will go into various arrays later. The text file looks like:
1 5.154600E-05 1.329887E-02 1.907202E-03 3 -1 8937 8889 1 0 890 1532 1533
2 4.639140E-03 9.845286E-03 1.659781E-02 1 9708 0 0 1617
3 1.329887E-02 1.329887E-02 1.108239E-02 4 8497 5442 0 5711 0 1 1611 1619 889 1618
4 1.030920E-04 5.154600E-05 1.412360E-02 3 -1 6966 6965 1 0 888 1620 1330
5 6.030882E-03 6.546342E-03 1.030920E-04 2 8238 6002 0 0 1622 1621
6 9.484464E-03 5.154600E-05 4.072134E-03 2 6104 5455 0 0 2481 1112
1st, I need to take out specific column (in this case 5th column). The size of lines are not equal, and I couldn't break reading after catching 5th column. cin.ignore didn't help.
2nd, 5th column is always an integer, say N, and then (maybe in a separate function) I need to read the LAST N number of same line and store them into arrays. I have no clue how to do it.
Here is part of code:
while (!myfile.eof())
{
// myfile.ignore (50, '\n'); // This is just a try. 5th col. always ends at 50th charachter of line. It didn't work!
double a,b,c,d,e;
myfile >> a >> b >> c >> d >> e;
if (minsize>e)
minsize=e;
if (maxsize<e)
maxsize=e;
frequency2[int(e)]++;
}
Any help ?
You could use std::getline to get the whole line in each iteration, and then use std::istringstream to parse out the columns. Something like this:
std::string buffer;
std::getline(myfile, buffer);
std::istringstream iss(buffer);
// Do your stuff
double a, b, c, d, e;
iss >> a >> b >> c >> d >> e;
I'd recomming you using a string with some reversed size like 60 bytes.
Then read char by char. If the char is a White space/Line break and the string size > 0 you should handle the data in the string and clear the data in the string. If the size == 0 you should continue.
void handle(std::string& data)
{
if(data.size())
{
//Handle Input
data.clear();
}
}
std::string buf(60);
while(file.isgood())
{
char c = file.get();
if(!file.isgood())
break;
switch(c)
{
case '\n':
case ' '://Probably you need more cases here just debug to find out
handle(buf);
break;
default:
buf.push_back(c);
break;
}
}
To complete others solutions:
getline is the good way to read a file line by line
you could use (boost) tokenizer to build an iterable from the line
you could use (boost) lexical cast to parse data from this iterable
something like
while(file.good())
{
string line;
getline(file, line);
if(line.empty())
continue;
boost::tokenizer<> tok(line);
boost::tokenizer<>::iterator tokiter = tok.begin();
double ex1 = boost::lexical_cast<double>(*tokiter);
tokiter++;
float ex2 = boost::lexical_cast<float>(*tokiter);
//etc..
cout << ex1 << " " << ex2 << endl;
}
http://www.boost.org/doc/libs/1_55_0b1/libs/tokenizer/tokenizer.html
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast.html

Problems getting values from ifstream correctly

**EDIT: I got it to work by changing the 'inStream >> next' to 'inStream >> skipws >> next'. In one of my earlier functions (to pull the last and first name) I had toggled noskipws. Apparently that toggle lasts between functions?
I have a program that is part of an assignment that is supposed to read a text file that is set up in the format of: "lastname firstname 1 2 3 4 5 6 7 8 9 10" (where each of the 10 numbers are integer scores).
I am able to read in the lastname and firstname fine, but when I go to start reading in the numbers, I am only able to read in the first one and then all the rest get set to 0.
Below is the function that is supposed to read the scores in. inStream has already had the lastname and firstname taken off. The textfile I am using has one line:
Tosis Halley 85 23 10 95 43 12 59 43 20 77
When run the program and print out the student.score values from 0 to 9, the first one displays correctly as '85' but all the reset show as '0'. Thoughts?
void GetScores (ifstream& inStream, record& student)
{
int score[10] = {-1, -1, -1, -1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1};
int next;
int counter = 0;
string test;
for (int i = 0; i < 10; i++)
{
inStream >> next;
student.score[i] = next;
}
}
Assuming the input is indeed all numbers, the function should actually work. However, you should always verify that inputs were indeed read correctly:
for (int i = 0; i != 10 && inStream >> next; ++i) {
student.score[i] = next;
}
if (!inStream) {
std::cout << "an input error occured\n";
}

Standard Deviation Program with While Loop cpp / c++

Hello everyone I am required to create a program that reads in an input file containing digits and then finds the standard deviation using the following method:
sqrt(( x1 - mu )^2 + ( x2 - mu )^2 + ( x3 - mu )^2 + ( x4 - mu )^2)/mu
The x's are equal to the digits read in, and mu is equal to the mean. I am having trouble doing this because I don't know how to set up different variables (x1, x2, x3, x4) for the values that are read in from the input file within my while loop. Also it is important to note that we are supposed to read in the first digit and then every third digit after that. This is what I have so far:
fin.open(FileName.c_str());
if (fin.fail())
{
cout <<"Bad file name or location.\n" ;
exit(0);
}
fin >> X;
first_score = X;
Counter = 0, Sum=0;
while (!fin.eof() )
{
Counter++;
if (Counter%3==0)
{
fin >> X;
Sum += X;
Counter++;
Counter2 ++ ;
Avg = (Sum+first_score)/(Counter2+1);
deviation = pow((X-Avg),2);
sum_of_deviations += deviation;
}
fin >> Score;
}
quotient_of_deviations = sum_of_deviations/Counter2;
standard_dev2 = sqrt(quotient_of_deviations);
fin.close();
I know this code is logically incorrect because I am subtracting a different mean from every x value. Does someone know how I could assign the X within the while loop to a new variable each time the while loop is ran? If I can do this, I will then be able to subtract each x value by the same mean outside of the loop. I hope I explained that good enough so that you guys can understand my problem. If not I will be happy to explain more. Thanks in advance for your time.
If you don't want to use arrays then you might have to read file multiple times.
int counter = 0;
int sum1=0;
ifstream fin,fin2; //fin and fin2 to read the file each time.
fin.open("myfile.txt"); //opening a file to read it.
while (!fin.eof() ) //reading a file
{
fin>>X;
sum1 = sum1+X; //adding all the numbers in the file
counter++; //counting number of items in the file
}
fin.close()
//Now first calculate mean
int mean=0;
mean = sum1/counter; //calculating the mean
//now calculate sum of squares of difference of each term and mean
int sum2=0;
fin2.open("myfile.txt"); //again opening the file with fin2
while (!fin2.eof() ) //again reading the file
{
fin2>>Y;
sum2 = sum2+ pow(Y-mean,2);
}
fin2.close()
//finally standard deviation
double sd=0;
sd = sqrt(sum2/mean); //calculating standard deviation
The problem with this is that you need to know the value of the average, but you won't know this until you have read in all the data. You are trying to calculate the deviation based on the average of the terms read in so far. This is incorrect
You should use the sqrt(Sum(x^2) /n - (sum(n) /n)^2) formula for the standard deviation.
Calculate the two sums in the loop, and then divide by n and complete the calculation at the end. Then you don't need to assign a new variable each time.