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.
Related
This is the file_processing_tutor.cpp file:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <cstdlib>
#include "ClientData.h"
using namespace std;
void outputline(int, const string &, double);
void outputlineDAT(ostream&, const ClientData &);
int main() {
cout << endl << "Phase 1 Writing Data to txt" << endl;
cout << "Make Sure Input is already ready before running" << endl;
ofstream outClientFile("C:/Users/User/Desktop/Streaming DT Data/test.txt", ios::out);
if(!outClientFile){
cerr << "File could not be opened" << endl;
exit(EXIT_FAILURE);
}
cout << "Enter the account, name, and balance" << endl << "Enter end-of-file to end input." << endl;
int count_input = 0;
int account;
string name;
double balance;
while(cin >> account >> name >> balance){
++count_input;
outClientFile << account << ' ' << name << ' ' << balance << endl;
cout << "? (Input Count = " << count_input << ") " << endl;
}
cout << endl << endl << "Phase 2 Reading Data from txt" << endl;
ifstream inClientFile("C:/Users/User/Desktop/Streaming DT Data/test.txt", ios::in);
if(!inClientFile){
cerr << "File Could not be Opened" << endl;
exit(EXIT_FAILURE);
}
cout << left << setw(10) << "Account" << setw(13) << "Name" << "Balance" << endl << fixed << showpoint;
while(inClientFile >> account >> name >> balance){
outputline(account, name, balance);
}
cout << endl << "Phase 3 Writing 100 Blank Records to Random Access File .Dat" << endl;
fstream outCredit("C:/Users/User/Desktop/Streaming DT Data/credit.dat", ios::out | ios::in | ios::binary);
if(!outCredit){
cerr << "File Could not be opened" << endl;
exit(EXIT_FAILURE);
}
ClientData blankClient;
for(int i = 0; i < 100; ++i){
outCredit.write(reinterpret_cast <const char *>(&blankClient), sizeof(ClientData));
}
cout << endl << "Phase 4 Writing Data Randomly to a Random Access File .Dat" << endl;
string firstName;
string lastName;
cout << "Enter Account Number (1 to 100, 0 to end input)\n?";
ClientData client;
cin >> account;
cout << "Account Input: " << account << endl;
while(account > 0 && account <= 100){
cout << "Enter lastname, firstname, balance \n?";
cin >> lastName >> firstName >> balance;
client.setAccountNumber(account);
client.setLastName(lastName);
client.setFirstName(firstName);
client.setBalance(balance);
outCredit.seekp((client.getAccountNumber() - 1) * sizeof(ClientData));
cout << "Enter Account Number (1 to 100, 0 to end input)\n?";
cin >> account;
}
return 0;
}
void outputline(int account, const string &name, double balance){
cout << left << setw(10) << account << setw(13) << name << setw(7)
<< setprecision(2) << right << balance << endl;
}
void outputlineDAT(ostream &output, const ClientData &record){
output << left << setw(10) << record.getAccountNumber() << setw(16)
<< record.getLastName() << setw(11) << record.getFirstName() << setw(10)
<< setprecision(2) << right << fixed << showpoint << record.getBalance() << endl;
}
Because I am using Sublime Text 3, I set my input in a file called inputf.in, this is all my raw input:
100 Jones 24.98
200 Doe 345.67
300 White 0
400 Stone -42.16
500 Rich 224.62
450 Harmond 412.5
3
Barker Doug 0
29
Brown Nancy -24.54
96
Stone Sam 34.98
88
Smith Dave 258.34
33
Dunn Stacey 314.33
0
And I see my output as follows from outputf.out:
Phase 1 Writing Data to txt
Make Sure Input is already ready before running
Enter the account, name, and balance
Enter end-of-file to end input.
? (Input Count = 1)
? (Input Count = 2)
? (Input Count = 3)
? (Input Count = 4)
? (Input Count = 5)
? (Input Count = 6)
Phase 2 Reading Data from txt
Account Name Balance
100 Jones 24.98
200 Doe 345.67
300 White 0.00
400 Stone -42.16
500 Rich 224.62
450 Harmond 412.50
Phase 3 Writing 100 Blank Records to Random Access File .Dat
Phase 4 Writing Data Randomly to a Random Access File .Dat
Enter Account Number (1 to 100, 0 to end input)
?Account Input: 450
Problem:
So every output in above was ok, until it reached phase 4 where I get to input new data for account variable, Instead of get the input 3 (which is set from the input) it reoutputs the last account data (450) ignoring the cin input. thus it didn't input anything to a file called credit.dat.
Appreciate any pointers to the issues, Thankyou!
I need to have my output look like this.
Applicant #: 1
School = L GPA = 4.0 math = 600 verbal = 650 alumnus = N
Applying to Liberal Arts
Accepted to Liberal Arts!!!
But when I run the code it just puts the input into every single place without going down the text file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
// Open both input and output
ifstream input;
input.open("MP2input.txt.");
ofstream output;
output.open("MP2output.txt");
// containers for any variables
double app = 0;
string pass;
if(!input.fail())
{
do(input >> pass)
{
app++;
output << "Application #" << app << endl;
output << "School = " << pass << " GPA = " << pass << " Math = " << pass << " Verbal = " << pass << " Alumnus = " << pass << endl;
}
}
input.close();
output.close();
}
The input must look like this
L 4.0 600 650 N
M 3.9 610 520 N
L 3.8 590 600 N
Output looks like this
Application #1
School = L GPA = L Math = L Verbal = L Alumnus = L
Application #2
School = 4.0 GPA = 4.0 Math = 4.0 Verbal = 4.0 Alumnus = 4.0
Application #3
School = 600 GPA = 600 Math = 600 Verbal = 600 Alumnus = 600
Application #4
Here:
do(input >> pass)
{
app++;
output << "Application #" << app << endl;
output << "School = " << pass << " GPA = " << pass << " Math = " << pass << " Verbal = " << pass << " Alumnus = " << pass << endl;
}
You read one string from the file and then print it mutliple times. input >> pass reads one word until it encounters a whitespace character. It is not clear how you expect output << "School = " << pass << " GPA = " << pass ... to print different entries from the file. Also you have a do without the while.
If you want to read multiple words from the file you rather need:
std::string school;
std::string GPA;
// ... others ...
while(input >> school >> GPA) {
app++;
output << "Application #" << app << endl;
output << "School = " << school << " GPA = " << GPA << endl;
// ... others ...
}
If you are sure your input file is well formatted just update pass from input each time.
int main()
{
// Open both input and output
ifstream input;
input.open("MP2input.txt.");
ofstream output;
output.open("MP2output.txt");
// containers for any variables
double app = 0;
string pass;
if(!input.fail())
{
do(input >> pass)
{
app++;
output << "Application #" << app << endl;
output << "School = " << pass;
input >> pass;
output << " GPA = " << pass;
input >> pass;
output << " Math = " << pass;
input >> pass;
output << " Verbal = " << pass;
input >> pass;
output << " Alumnus = " << pass << endl;
}
}
input.close();
output.close();
}
Better to be a little more robust and check input.fail() each time but that's a lot of typing ;-)
How should I edit the specific line in a text file? And how should I avoid overwriting issue. ( How do I keep the record I had added before instead of replacing them by the new records?)
I tried to use line.replace but it says " No matching member function for call to replace ".
else if(choice == 4){
// count++;
string edit;
string newdate;
double newincome;
double newoutcome;
double EditTodayBalance = 0;
string emptySpace = " ";
// string sentence;
cout << " There are " << count << " record(s) in the file " << endl;
cout << " Please enter the date to edit " << endl;
cin >> edit;
size_t pos;
ifstream Record("BankRecord.txt");
if (Record.is_open()) {
while (getline(Record, line)) {
pos = line.find(edit);
if (pos != string::npos) // string::npos is returned if
string is not found
{
cout << line << endl;
cout << " Enter what you want to replace " << endl;
cout << " Please enter the new date you want to put " << endl;
cin >> newdate;
cout << " Please enter the new income you want to put " << endl;
cin >> newincome;
cout << " Please enter the new outcome you want to put " << endl;
cin >> newoutcome;
cout << " Your new Record is " << endl;
cout << count << emptySpace << newdate << emptySpace << newincome << emptySpace << newoutcome << endl;
//line.replace()
}
}
}
EditTodayBalance = newincome - newoutcome;
cout << " Today's balance is " << EditTodayBalance << endl;
cout << " Please reenter your choice " << endl;
cin >> choice;
}
I expect if the old line is " 1 2/2/2019 32 21 " and I input the new line to be " 1 2/3/2019 22 11 ". Then when I open the file the record will be the new one.
I'm afraid you will have to re-write the entire file. Read the content of the file line by line, store it in memory (maybe a vector of strings). Now do your editing on the specified line in that vector. When the operation is complete, dump the entire content of vector in another file. You may later replace the original file.
I'm building a program for my class the requires us to import data from a .txt file and the item names/ prices will be used to calculate saltes tax and grand total. My teacher put this up as an example, but I can't get it to run.
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
int main()
{ // Beginning of main function
string name;
ifstream data_in;
ofstream data_out;
int cnt=0;
int number;
struct Item
{
int item_n;
char disc[50];
float price;
};
Item store[999];
data_in.open("cost.txt");
data_out.open("file_out.txt");
while(!data_in.eof())
{
//cout << "Enter in the item number: ";
data_in >> store[cnt].item_n;
//cout << "Enter in the description for item number " << store[cnt].item_n << ": ";
data_in >> store[cnt].disc;
//cout << "Enter in the price for the " << store[cnt].disc << ": $";
data_in >> store[cnt].price;
cnt++;
}
cout << endl << endl;
number = cnt;
for (cnt=0; cnt<number; cnt++)
{
name = store[cnt].disc;
cout << setw(5) << store[cnt].item_n << " " << store[cnt].disc << setw(16-name.length()) << "$" << setw(9) << store[cnt].price << endl;
}
for (cnt=0; cnt<number; cnt++)
{
name = store[cnt].disc;
data_out << setw(5) << store[cnt].item_n << " " << store[cnt].disc << setw(16-name.length()) << "$" << setw(9) << store[cnt].price << endl;
}
return 0;
}
And this is the information in the cost.txt file
Books 45.01
Pens 21.03
Pencils 10.90
Hats 50.00
Caps 800.00
Food 1.00
The code you've written reads three things for each Item: the item number, the description, and price.
The sample data file you shown contains only two things for each item: what looks to be a description, and a price.
The expected data format does not match the contents of the input file. This code will never work, as is. One or the other is wrong. Plus all the other problems with the code, as mentioned in the comments.
Try the following changes, the rest of your code seems to work:
data_in.open("cost.txt");
data_out.open("file_out.txt");
if (!data_in.is_open() || !data_out.is_open()) //Test if files opened correctly...
{
cout << "Failed to open a file!\n";
return 1;
}
float SalesTotal = 0;
while(true)
{
if (!(data_in >> store[cnt].disc))
{
//Failed to read first element in this record - could be eof or format error
if (data_in.eof())
break; //eof - all records read.
cout << "Format error first field\n";
return 1; //format error on first field.
}
if (!(data_in >> store[cnt].price))
{
cout << "Format error second field\n";
return 2; //format error on second field.
}
store[cnt].item_n = cnt + 1; //Item number is not a field in your file, use the counter...
SalesTotal += store[cnt].price;
cnt++;
}
if (!cnt)
{
cout << "No records read\n";
return 3; //No valid records read.
}
float GrandTotal = ((SalesTotal / 100) * 6) + SalesTotal;
cout << "Sales total: " << SalesTotal << " Grand total:" << GrandTotal << "\n";
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.