How to get my program to read thru errors - c++

I have an assignment for school in which the goal is to read data from a text file, and output calculations made with the info. I've gotten the inputing and outputting mostly down, but our prof wants us to include error checking aswell. I've done error checking for strings, and now im working on ints/doubles. The only issue is when i try to use the sample error input file he provided, my while loop dosen't fire at all.
bool isWord(string s)
{
for (int i = 0; i < s.length(); ++i)
{
if (::isdigit(s[i])){
return false;
}
}
return true;
}
int main()
{
ifstream inData;
ofstream outData;
inData.open("inData.txt");
outData.open("outData.txt");
//check for Error
if (inData.fail()){
cout << "Error opening file!" << endl;
exit(1);
}
if (outData.fail()){
cout << "Error opening file!" << endl;
exit(1);
}
double rWidth;
double rLength;
double cRad;
double number = 0;
string fName;
string lName;
string word;
int age;
int i = 0;
int savings;
int count = 0;
int people = 0;
int tAge = 0;
int tSavings = 0;
string names[256];
double tLength = 0;
double tWidth = 0;
double tArea = 0;
double perimeter = 0;
double tRad = 0;
double tCarea = 0;
double tCirc = 0;
while(inData >> rWidth >> rLength >> cRad >> fName >> lName >> age >> savings){
cout << rWidth << " " << rLength << " " << cRad << " " << fName << " " << lName << " " << age << " " << savings << "\n";
stringstream fNameStream(fName);
stringstream lNameStream(lName);
while (fNameStream >> word)
{
if (isWord(fName))
{
names[count++] = word;
}
else
{
names[count++] = "John";
}
}
while (lNameStream >> word)
{
if (isWord(lName))
{
names[count++] = word;
}
else
{
names[count++] = "Doe";
}
}
istringstream widthStream(rWidth);
while (widthStream >> number)
{
if (widthStream >> number)
{
widthStream >> rWidth;
}
else
{
rWidth = 0.0;
}
}
tLength = tLength + rLength;
tWidth = tWidth + rWidth;
perimeter = perimeter + (2*(rWidth+rLength));
tArea = tArea + (rWidth*rLength);
tRad = tRad + cRad;
tCarea = tCarea + pow(cRad, 2) * M_PI;
tCirc = tCirc + (2*M_PI*cRad);
tAge = tAge + age;
tSavings = tSavings + savings;
}
cout << tLength << "\n";
cout << tWidth << "\n";
cout << perimeter << "\n";
cout << tArea << "\n";
cout << tCarea << "\n";
cout << tCirc << "\n";
cout << tAge << "\n";
cout << tSavings < "\n";
cout << count << "\n";
while (i < count)
{
cout << names[i] << " ";
i++;
}
outData << "Rectangle: \n";
outData << "The total length= " << tLength << ", width= " << tWidth << ", area= " << tArea << "\n";
outData << "Perimeter= " << perimeter << "\n\n";
outData << "Circle:\n";
outData << "The total radius= " << tRad << ", area= " << tCarea << ", circumference= " << tCirc << "\n\n";
outData << "People:\n" << "Total number of people= " << count << "\n" << "Total Age= " << tAge << "\nTotal Savings= " << tSavings;
inData.close();
outData.close();
system("pause");
return 0;
}
Hopfully thats formatted correctly.
The program runs fine and dandy when i use:
10.45 8.76
13.78
Jake Melon 45
7600
128 76.9
11
Mike Sander 56
800
15.9 43
6400
David James 32
87000.54
But when i use:
10.45 aaaa
13.78
Jake Melon 45
7600
128 76.9
;
Mike Sander 23
800
15.9 43
w
David James i
87000.54
My main while loop (where I read data) doesn't fire for some reason, and all of my values remain at 0. Your help will be greatly appreciated! And I'm sorry for such a long block of text.

Error recovery is difficult and there are no standard methods (think about how your compiler recovers from a syntax error).
You will need an outer loop for your while loop. You'll want to come up with a design that will help you resynchronize on the input format. Again, not an easy task.
A simple method is to count the text lines and display the text line where the failure existed and end the program. From that you can display more information, such as the field that was in error. Some programmers assume the worst that once an error is found the remaining data can't be trusted.
I recommend putting in place a simple error announcement and safely terminate (clean up, flush to disk, etc.). Work on getting the remainder of your program working correctly, then come up with better error handling strategies.

Related

c++ while loop from file with different data types

I have a file that includes this information:
Bev Powers
3
76 81 73
Chris Buroughs
5
88 90 79 81 84
Brent Mylus
2
79 81
I have a count controlled loop that will do the first 3 lines and use the information correctly but I am struggling with a loop that will reuse the the loop until all the information is displayed from the file regardless of how many golfers with matches are on the file. I am asking for pointers in the right direction, any assistance would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream inScores;
string filename;
string name;
int loopCount, matchScore;
int count = 1;
float mean = 0;
float adder = 0;
int main()
{
cout << endl << "Enter the golfer's filename: ";
getline(cin,filename);
cout << endl;
inScores.open(filename.c_str());
if(!inScores)
{
cout << "** " << filename << " does not exist. Please ";
cout << "check the spelling and rerun ";
cout << "the program with an existing golfer file. ** " << endl << endl;
return 1;
}
getline(inScores,name);
inScores >> loopCount;
cout << name << " has " << loopCount << " matches with scores of" << endl << endl;
inScores >> matchScore;
while (count <= loopCount)
{
cout << "Match " << count << ": " << matchScore << endl;
adder = adder + matchScore;
adder = adder + matchScore;
inScores >> matchScore;
count++;
}
cout << endl;
int(mean) = .5 + (adder / loopCount);
cout << "The mean score is " << mean << endl << endl;
inScores.close();
return 0;
}
As stated using loops will be necessary to get what you want. Also since the getline and extraction return false if they fail you can use them for the test in the loop:
ifstream inScores;
string filename;
string name;
int loopCount , matchScore;
int count = 1;
float mean = 0;
float adder = 0;
int main()
{
cout << endl << "Enter the golfer's filename: ";
getline( cin , filename );
cout << '\n';
inScores.open( filename );
if ( !inScores )
{
cout << "** " << filename << " does not exist. Please ";
cout << "check the spelling and rerun ";
cout << "the program with an existing golfer file. ** " << "\n\n";
return 1;
}
while ( getline( inScores , name ) )
{
if ( inScores >> loopCount )
{
cout << name << " has " << loopCount << " matches with scores of" << "\n\n";
}
else
{
cout << "File read error";
return 1;
}
for ( int count = 1; count <= loopCount; count++ )
{
if ( inScores >> matchScore )
{
cout << "Match " << count << ": " << matchScore << '\n';
adder = adder + matchScore;
}
else
{
cout << "File read error";
return 1;
}
}
}
cout << '\n';
int( mean ) = .5 + ( adder / loopCount );
cout << "The mean score is " << mean << "\n\n";
inScores.close();
return 0;
}

C++ Not inserting first line of data to output file

I'm relatively new to C++, and have been working my way through taking a data file and reading it, then taking that data doing some math with some of it, and then exporting it all to an output file. However my problem is everytime it runs it skips writing the very first line to the output file.
My data file is:
Jon Doe 15 7.25
Nick Delgado 8 7.25
Jo Barnes 4 7.25
Harold Griffith 45 11.00
Linda Holmes 30 10.00
My output looks like this:
Nick Delgado 8 7.25 58 0 58
Jo Barnes 4 7.25 29 0 29
Harold Griffith 45 11 522.5 146.3 376.2
Linda Holmes 30 10 300 84 216
It's completely skipping writing out any information concerning Jon Doe. Which is:
Jon Doe 15 7.25 108.75 0 108.75
I've tried multiple different ideas, asked my friends, and overall I'm extremely frustrated.
I figure the problem code is in here somewhere:
if (!dataOutFile.is_open()) {
cout << "Couldn't open file";
}
else {
dataOutFile << firstName << " " << lastName << " " << hoursWorked << " " << payRate << " " << grossPay << " " << withHolding << " " << takeHomePay << endl;
cout << "What was wrote to file: \n" << firstName << " " << lastName << " " << hoursWorked << " " << payRate << " " << grossPay << " " << withHolding << " " << takeHomePay << endl;
}
Because my output window looks like this:
So what that tells me is that it is getting to the code where it writes to the file because it's writing the other four entries past the first one. But also according to the output window it is writing to the file the information that it should- but for some reason it isn't. I'm using the append command so it shouldn't be overwriting anything, and according to the output file it isn't but maybe the first line.
No errors, or warnings, and my debug logs are free of errors. Please help me, any help is appreciated. I also realize the code is kinda messy, and I need to break it down into more functions but I'm just trying to get this to work, and then I can clean it up.
The full code for my program that handles all of this is below, in case anyone needed to see it.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// Global Variables
string fileName;
double totalGrossPay = 0;
double totalWithHolding = 0;
double totalTakeHomePay = 0;
double withHoldingLimit = 200;
double withHoldingRate = .28;
double overtimeRate = 1.5;
// Initialize Functions
void readFile();
int main() {
cout << "What is the name of your file?" << endl;
getline(cin, fileName);
readFile();
}
void readFile() {
// Variables
string firstName;
string lastName;
double hoursWorked;
double payRate;
double grossPay;
double withHolding;
double takeHomePay;
double overtime;
string dataOutFileName = "Salary.out";
// Intialize and Open Input File
ifstream file;
file.open(fileName);
// Initialize Output File
ofstream dataOutFile(dataOutFileName);
// Check to see if file failed to open
if (!file.is_open()) return;
// Define variables needed in the while loop.
string word;
int i = 1;
// Actually reads through the file and prints out what the file has.
while (i != 0) {
// Pull up the next word in the word file
file >> word;
// Firstname
if (((i - 1) % 4) == 0) {
firstName = word;
cout << "First name: " << firstName << "\n";
}
// Last name
else if (((i - 1) % 4) == 1) {
lastName = word;
cout << "Last name: " << lastName << "\n";
}
// Hours Worked
else if (((i - 1) % 4) == 2) {
hoursWorked = atof(word.c_str());
cout << "Hours Worked: " << hoursWorked << "\n";
}
// Pay Rate
else if (((i - 1) % 4) == 3) {
payRate = atof(word.c_str());
cout << "Pay Rate: " << payRate << "\n";
}
// Add 1 to i
i++;
// If i-1 divides into 4 with no remainder, move to new line
// Also since we now have all four variables filled in we can do our math
if (i > 3 && ((i - 1) % 4) == 0) {
// Gross Pay
if (hoursWorked > 40) {
overtime = hoursWorked - 40;
}
else {
overtime = 0;
}
if (overtime != 0) {
grossPay = (40 * payRate) + (overtime * (payRate * overtimeRate));
}
else {
grossPay = hoursWorked * payRate;
}
// Withholding
if (grossPay > withHoldingLimit) {
withHolding = grossPay * withHoldingRate;
}
else {
withHolding = 0;
}
// Take Home pay
takeHomePay = grossPay - withHolding;
// Add to totals
totalGrossPay += grossPay;
totalWithHolding += withHolding;
totalTakeHomePay += takeHomePay;
// Write to file, and print the line so we know it worked!
dataOutFile.open(dataOutFileName, fstream::app);
// Check it if is open
if (!dataOutFile.is_open()) {
cout << "Couldn't open file";
}
else {
dataOutFile << firstName << " " << lastName << " " << hoursWorked << " " << payRate << " " << grossPay << " " << withHolding << " " << takeHomePay << endl;
cout << "What was wrote to file: \n" << firstName << " " << lastName << " " << hoursWorked << " " << payRate << " " << grossPay << " " << withHolding << " " << takeHomePay << endl;
}
dataOutFile.close();
// move to new line
cout << "\n";
}
// Check to see if were at the end of the file, if so end while.
if (file.eof()) {
i = 0;
}
}
file.close();
}
The i-based state machine is way too complex and totally not needed here. Don't fix it, throw it away.
If you need to read four things, read four things at once. Do it inside the while condition.
ifstream file(filename);
ofstream dataOutFile(dataOutFileName);
while (file >> firstName >> lastName >> hoursWorked >> payRate)
{
// you have all four pieces of data
// calculate and print what you need here
}
Do not call close() or check for eof() inside the loop.

c++ infile extraction checking if int

I'm fairly new to C++ and have no idea where to start with this or if its even possible, but i'm trying to check to see if length, width, radius, etc are actually doubles and if they are not return 0.
int main() {
ifstream inFile;
ofstream outFile;
string in;
double length, width, tLength = 0, tWidth = 0, areaRec, tAreaRec = 0, parameter, tParameter = 0;
double radius, tRadius = 0, areaCirc, tAreaCirc = 0, circumference, tCircumference = 0;
double savings, tSavings = 0;
int people = 0, age, tAge = 0;
string name1, name2;
inFile.open("inData_with_error.txt");
outFile.open("outData_Normal.txt");
outFile << fixed << showpoint << setprecision(2);
if (!inFile) {
cout << "ERROR: Unable to open file!" << endl;
inFile.close();
}
else {
cout << "Caculating..." << endl;
while (inFile >> length >> width >> radius >> name1 >> name2 >> age >> savings) {
cout << length << ", " << width << ", " << radius << ", " << name1 << ", " << name2 << ", " << age << ", " << savings << endl;
tLength = tLength + length;
tWidth = tWidth + width;
parameter = length * 2 + width * 2;
areaRec = length * width;
tParameter = tParameter + parameter;
tAreaRec = tAreaRec + areaRec;
tRadius = tRadius + radius;
areaCirc = pow(radius, 2) * PI;
circumference = (radius * 2) * PI;
tAreaCirc = tAreaCirc + areaCirc;
tCircumference = tCircumference + circumference;
people = people + 1;
tAge = tAge + age;
tSavings = tSavings + savings;
}
}
cout << "Done" << endl;
outFile << "Rectangle:" << endl << "Total length = " << tLength << ", " << "Total width = " << tWidth << ", " << "Total area = " << tAreaRec << ", " << "Total parameter = " << tParameter << endl << endl
<< "Circle:" << endl << "Total radius = " << tRadius << ", " << "Total area = " << tAreaCirc << ", " << "Total circumference = " << tCircumference << endl << endl
<< "Person: " << endl << "Total number of persons = " << people << endl << "Total age = " << tAge << endl << "Total savings = " << tSavings << endl;
inFile.close();
outFile.close();
system("pause");
return 0;
}
For example if my data with error is the below i want to catch the char and strings and return a 0 but have no idea how to tackle this question. Can someone lead me into the right direction?
10.45 aaaa
13.78
Jake Melon 45
7600
128 76.9
;
Mike Sander 23
800
15.9 43
w
David James i
87000.54
After the end of the while loop, you can add a test to check to whether the while loop got terminated due to EOF or due to an error in reading the data.
while (inFile >> length >> width >> radius >> name1 >> name2 >> age >> savings) { ... }
if ( inFile.eof() )
{
// No errors in reading data
}
else
{
// Error in reading data.
// Deal with error
}

When writing to a file, only the last line saves to my output file

Im trying to write to a file but only the last line gets written to the file. I've tried opening and closing the file outside the loop but then nothing writes to the file
void getValues (double totalEnergy, double meanPowerConsumption, double maxPowerConsumption);
int main()
{
double totalEnergy, meanPowerConsumption, maxPowerConsumption;
getValues(totalEnergy, meanPowerConsumption, maxPowerConsumption);
return 0;
}
void getValues(double totalEnergy, double meanPowerConsumption, double maxPowerConsumption)
{
int x = 0;
int c = 0;
double p = 0;
int i = 0;
ifstream inFile;
inFile.open("data.txt");
if (inFile.fail())
{ cerr << "Error opening file." << endl;
exit(1);
}
// Declaring variables.
double power1, power2, time1, time2, totalPower, timeConstant, changeInPower, totalTime, time, coloumns;
double year, month, day, hour, minute, second, voltage, current, frequency;
double accumulatedPower=0;
while(!inFile.eof())
{
inFile >> year >> month >> day >> hour >> minute >> second >> voltage >> current >> frequency;
//Should have taken into account 'Years','Months' and 'Days' but its throws the calculations into exponents.
time2 = ((3600*hour) + (minute *60) + second);
if (x==0)
{
timeConstant = 0;
time1 = 0;
totalTime = 0;
}
else
{
timeConstant = time2 - time1;
totalTime = totalTime + timeConstant;
}
//cout << "time1: " << time1 << endl;
//cout << "time2: " << time2 << endl;
//cout << "Time Constant: " << timeConstant<< endl;
//cout << "Total Time" << totalTime << endl;
power2 = voltage*current;
if (x==0)
{
power1 = 0;
changeInPower = 0;
totalPower = 0;
totalEnergy = 0;
meanPowerConsumption = 0;
}
else
{
changeInPower = (power1 + power2)/2;
totalPower = totalPower + changeInPower;
}
// cout << "Counter" << c << endl;
// Assumed that mean powerconsumption is the average of all powers entered.
meanPowerConsumption = totalPower / c;
// Testing Variables.
//cout << "power1: " << power1 << endl;
//cout << "power2: " << power2 << endl;
//cout << "Change in Power: " << changeInPower << endl;
//cout << "total Power: " << totalPower << endl;
//Numerical Integration:
totalEnergy = totalEnergy + (timeConstant*changeInPower);
//Counter Loop:
if (power2 > maxPowerConsumption)
{
maxPowerConsumption = power2;
}
accumulatedPower = accumulatedPower + power1;
time = time2 - time1;
p = p + time;
ofstream outFile;
outFile.open("byhour.txt");
for (coloumns=0; p>=3599; coloumns++)
{
i++;
outFile << i << " " << accumulatedPower/3600000 << endl;
accumulatedPower=0;
p=0;
}
outFile.close();
cout << "coloumns: " << i << endl;
cout << "P value " << p << endl;
cout << "accumulated power" << accumulatedPower << endl;
cout << "The total Energy is: " << totalEnergy/3600000 << "KwH" << endl;
cout << "The mean power consumption is: " << meanPowerConsumption << endl;
cout << "The Max Power Consumption is:" << maxPowerConsumption << endl;
cout << endl ;
c++;
x++;
time1 = time2;
power1 = power2;
}
ofstream outStats;
outStats.open("stats.txt");
outStats << totalEnergy/3600000 << endl;
outStats << meanPowerConsumption << endl;
outStats << maxPowerConsumption << endl;
outStats.close();
}
That's the full code. I tried taking it out and putting it back in (open and close file). Nothing has worked so far
You are opening and closing the file in a loop; based on the default mode it's opening to the first position in the file, so each write you are opening the file, writing to the start of the file (likely overwriting what was there before), and closing it.
You should open the file once, write out in a loop, and close outside the loop.
Your for loop is actually running (at most) once.
for (coloumns=0; p>=3599; coloumns++)
{
...
p=0;
}
Assuming p is at least 3599 at the start of the loop, the loop will run only a single time, because p gets set to 0 at the end of the loop (meaning the test will be false the next time around and the loop stops).
If p is less than 3599 at the start, of course, it won't run at all.

Password count help

void getPassword()
{
while (true)
{
string password;
cout << "Enter the password: ";
getline(cin, password);
if (password == "123456") break;
cout << "INVALID. ";
} // while
} // getPassword
int main()
{
getPassword();
double P;
double r;
double N = 360;
double rate;
cout << "What's the mortgage amount? ";
cin >> P;
cin.ignore(1000, 10);
cout << "What's the annual interest rate? ";
cin >> r;
cin.ignore(1000, 10);
rate = r / 100 / 12;
// (p * (1 + r)n * r) / ((1 + r)n - 1)
double M = P * ((pow))(1 + rate, N) * rate / (((pow))(1 + rate, N) -1);
cout.setf(ios::fixed|ios::showpoint);
cout << setprecision(2);
cout << "Principal = $" << P << endl;
cout.unsetf(ios::fixed|ios::showpoint);
cout << setprecision(6); // resets precision to its default
cout << "Interest Rate = " << r << "%" << endl;
cout << "Amortization Period = " << N / 12 << " years" << endl;
cout << "The monthly payment = $" << M << endl;
ofstream fout;
fout.open("mortgages.txt", ios::app);
if (!fout.good()) throw "I/O error";
fout.setf(ios::fixed|ios::showpoint);
fout << setprecision(2);
fout << "Principal = $" << P << endl;
fout.unsetf(ios::fixed|ios::showpoint);
fout << setprecision(6); // resets precision to its default
fout << "Interest Rate = " << r << "%" << endl;
fout << "Amortization Period = " << N / 12 << " years" << endl;
fout << "The monthly payment = $" << M << endl;
fout.close();
return 0;
}
What's up guys? I have a homework assignment for comsc and I have hit a roadblock in my last program. What I am attempting to do is limit the user of this program to 3 invalid password attempts. Do I need to change this to a value-returning subprogram or can I accomplish this without doing so? Any help would be much appreciated!!
Easiest way would be to change getPassword so that it returns a bool that signifies whether the user put in the right password. Then, rather than while (true), say for (int i = 0; i < 3; ++i)...and rather than break, return true. After the loop, return false since they went 3 rounds without putting in the right password.
In the rest of the program, rather than just calling getPassword, check its return value. If it's false, print an error message and exit.
Something like:
bool checkPassword() { // renaming this, since it doesn't just *get* a password
for (int i = 0; i < 3; ++i) {
string password;
std::cout << "Enter password: " << std::flush;
std::getline(std::cin, password);
if (password == "123456") return true;
std::cout << "INVALID.\n";
}
std::cout << "Maximum attempts exceeded.\n";
return false;
}
int main() {
if (!checkPassword()) {
return 1;
}
... rest of main() here ...
}