My assignment states the following :
Three employees in a company are up for a special pay increase. You are given a file, Ch3_Ex7Data.txt, with the following data:
Miller Andrew 65789.87 5
Green Sheila 75892.56 6
Sethi Amit 74900.50 6.1
Each input line consists of an employee's last name, first name, current salary, and percent pay increase.
For example, in the first input line, the last name of the employee is Miller, the first name is Andrew, the current salary is 65789.87, and the pay increase is 5 %.
Write a program that reads data from the specified file and stores the output in the file Ch3_Ex7Output.dat. For each employee, the data must be output in the following form: firstName lastName updatedSalary Format the output of decimal numbers to two decimal places.
My code is the following.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
//Declaring the variables
string firstName;
string lastName;
double payIncrease;
double pay;
ifstream inFile;
ofstream outFile;
inFile.open("C:\\Users\\Megan\\Ch3_Ex7Data.txt"); //opens the input file
outFile.open("C:\\Users\\Megan\\Ch3_Ex7Output.dat"); //opens a output file
outFile << fixed << showpoint;
outFile << setprecision(2); // Output file only having two decimal places
cout << "Processing Data....." endl; //program message
while (!inFile.eof() //loop
inFile >> lastName >> firstName >> pay >> payIncrease;
pay = pay*(pay*payIncrease);
outFile << firstName << " " << lastName << " " << pay << "/n";
inFile.close();
outFile.close();
return 0;
}
For some reason I cannot seem to get the code to open my existing .txt file, read it and then translate it to another file. Does anybody see anything wrong with this that could help me out?
You have many problems with you code.
The two most evident prevent the program from compiling:
cout << "Processing Data....." endl; //program message
should be:
cout << "Processing Data....." << endl; //program message
and while (!inFile.eof() //loop should be at least while (!inFile.eof() )//loop
That's not all:
while (!inFile.eof()) is an anti-idiom: you test for end of file, then read and do the processing even if an error or end of file has occured. You must test after reading.
And as you were said in comment, without { } only the first line after the while is repeated, which is not what you want.
The correct formula to add a percent increase is pay = pay*(1 + payIncrease/100.); at least pay = pay+(pay*payIncrease/100.);
Adding a '/n' as an end of line is plain wrong. The character is '\n' (note the backslash), and anyway you should always write endl in C++.
Once all that is fixed, the loop becomes:
for (;;) { //loop
inFile >> lastName >> firstName >> pay >> payIncrease;
if (! inFile) break; // exit on eof or error
pay = pay*(1 + payIncrease/100.);
outFile << firstName << " " << lastName << " " << pay << endl;
}
and the output is:
Andrew Miller 69079.36
Sheila Green 80446.11
Amit Sethi 79469.43
But is you want to learn good pratices, you should also:
test the opening of both files
test after end of loop if the termination was caused by an error and issue a warning
last by not least learn to use a debugger...
This was my solution
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main() {
// Write your main here
//Declarations
string FirstName;
string LastName;
double Pay;
double Increase;
double UpdatedSalery;
//File object and open txt and dat files per instructions and use user input for the txt input file
ifstream FileIn;
string FileName;
cout << "enter a file name: ";
cin >> FileName;
FileIn.open(FileName);
ofstream FileOut("Ch3_Ex5Output.dat");
FileOut << setprecision(8);
while(FileIn >> LastName >> FirstName >> Pay >> Increase){
UpdatedSalery = ((Pay*(Increase/100))+Pay);
FileOut << " " << FirstName << " " << LastName << " " << UpdatedSalery << endl;
}
FileIn.close();
FileOut.close();
return 0;
}
Related
I am attempting to write a program for homework which reads the contents of a notepad file and displays the contents and the number of words int he file. My code currently outputs nothing when I enter the name of the names of files I am using to test the program, and the input validation while loop I inserted does not function either.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//Declare needed variables
string fileName, contents;
int wordCount = 0;
ifstream inData;
//Display program info
cout << "*** A SIMPLE FILE PROCESSING PROGRAM ***" << endl;
//Prompt user input
cout << "Enter a filename or type quit to exit: ";
cin >> fileName;
inData.open(fileName.c_str());
//Inform the user when their input is invalid and ask them to input another
file name
while (!inData)
{
inData.clear();
inData.ignore(200, '\n');
cout << "File not found. Please type a correct file name." << endl;
cin >> fileName;
inData.open(fileName.c_str());
}
inData >> contents;
//Read and output the contents of the selected file
while (inData)
{
cout << fileName << " data\n";
cout << "***********************" << endl;
inData >> contents;
wordCount++;
cout << contents << endl;
inData >> contents;
}
//Display the number of words in the file
cout << "***********************" << endl;
cout << fileName << " has " << wordCount << " words." << endl;
inData.close();
return 0;
}
The code compiles in its current state [but does not produce the desired outcome.
I will show you one of the many possible solutions.
But I would not recomend, to check the validity of a filename in a loop. You will give the user no chance to escape. Hence, I propose to open the file, and, if that does not work, show an error message and quit.
Then, what sounds easy in the beginning like, count the words, is not really that easy. What is a word? Characters only, or characters mixed with digits or even an underscore in it like for C++ variable names? Needs to be defined.
Additionally you may have separators like commas or one and more other white spaces. So a line like "Hello,,,,World" cannot be so easily counted. If you try to read the 2 words, then you will see a surprise.
std::string s1{};
std::string s2{};
std::istringstream iss("Hello,,,,World");
iss >> s1 >> s2;
Will read everything in s1!
The solution is that we define clearly what a word is. And this we will do with a std::regex. In the below example we use characters, digits and _
Then we use the regex_iterator to find all occurences of the regex (the word) in the line. We substract the end from the beginning with std::distance, which will give us the count of the words.
Then we give an output to the user in whatever format.
It may seem complicated. But it is precise. And rather flexible. Try to anaylze line by line and you will understand it.
Please see:
#include <iostream>
#include <string>
#include <regex>
#include <fstream>
#include <iomanip>
int main()
{
// Get a filename from the user
std::cout << "Enter a filename:\n";
std::string filename{}; std::cin >> filename;
// Try to open and read the file
std::ifstream fileStream(filename);
if (fileStream) {
// We will count all words
size_t numberOfWordsOverall{ 0 };
// We will also count the lines in the file
size_t lineCounter{ 1 };
// Define, what a word is. In this case: Characters, Digits and _
std::regex regexForWord("[\\w\\d_]+");
// Read all lines in file
std::string line{};
while (std::getline(fileStream, line)) {
// Count the numbers of words in one line
const size_t numberOfWordsInLine = std::distance(
std::sregex_token_iterator(line.begin(), line.end(), regexForWord, 1),
std::sregex_token_iterator()
);
// Update the overall word counter
numberOfWordsOverall += numberOfWordsInLine;
// Show result to user
std::cout << "# " << std::left << std::setw(2) << lineCounter++ << " (Words in line: "<< std::setw(2) << numberOfWordsInLine <<
" Words overall: " << std::setw(4) << numberOfWordsOverall << ") Line content --> " << line << '\n';
}
}
else {
std::cerr << "Could not open file '" << filename << "'\n";
}
return 0;
}
Hope this helps . . .
So I have a .txt file I'm supposed to be reading information in from and displaying in a neat little table. Here's a snippet of the .txt files contents
in the format
Farm name, item count, item, price, total price
Collins Farm, 43900 tomatoes 0.67 29413
Bart Smith Farms, 34910 cassavas 0.99 34560.9
Allen Farms, 117 coconuts 0.54 63.18
etc...
It should print out in the console as
Collins Farm (some spaces here) 43900 items contributed totaling $29413.00
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
int addLine(int);
int main()
{
using std::ifstream;
ifstream myFile;
myFile.open("ASSGN6-B.txt");
string farmName;
int itemCount;
string itemName;
double itemPrice;
double totalPrice;
if (!myFile)
{
cout << "File open failed!" << endl;
}
else
{
cout << "\t\t\t=========================================================" << endl;
cout << "\t\t\t= FARMER'S MARKET INVENTORY =" << endl;
cout << "\t\t\t=========================================================" << endl;
while (myFile.good())
{
getline (myFile, farmName);
getline (myFile, itemName);
myFile >> itemName >> itemPrice >> totalPrice;
cout << farmName << " " << itemCount << " items contributed totaling $" << totalPrice << endl;
}
}
myFile.close();
return 0;
}
This is what I've been messing with trying to figure out how this input stuff works. I guess what I really don't get is how it's supposed to know which item is which. I previously thought it just read in a line at a time only but theres's gotta be a way to separate the items even on the same line and print them all separately in the console.
Also, some farm names appear twice in the .txt file and I'm supposed to combine their data into one line if it's a duplicate. Help with this would be appreciated too.
Thanks.
First piece of advice:
Don't use
while (myFile.good()) { ... }
You need to make sure that the data you expect to read are indeed read successfully.
See Why is iostream::eof inside a loop condition considered wrong? to understand why.
Coming to the other problems...
The line
getline (myFile, farmName);
will read an entire line to farmName. That's not what you want. You want to read everything up to the comma (,) character. std::getline has such an option. Use
getline (myFile, farmName, ',');
It's not clear what you were hoping to accomplish by
getline (myFile, itemName);
That line can be removed.
Looking at the sample data, all you need is
myFile >> itemCount >> itemName >> itemPrice >> totalPrice;
to read rest of the data.
However, after you read them, make sure to ignore the everything in that line. You can use istream::ignore for that.
Here's my suggestion.
while ( getline(myFile, farmName, ',') &&
(myFile >> itemCount >> itemName >> itemPrice >> totalPrice) )
{
cout << farmName << " " << itemCount << " items contributed totaling $" << totalPrice << endl;
// Ignore rest of the line
myFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Make sure to add
#include <limits>
to be able to use std::numeric_limits.
I think you should try to do more research to understand file operations in c++, but I noticed a few things with your code:
getline(myFile, farmName);
This line will take the entire line of the file it's reading and store it into farmName. It basically reads the line until it finds the end of line character. I think your intention was for the line to read until the comma for the farm name, thus you would use:
getline(myFile, farmName, ',');
The third parameter is an optional delimiting character that tells getline what character to look for to stop reading at.
The next lines that I noticed are:
getline(myFile, itemName);
myFile >> itemName >> itemPrice >> totalPrice;
Why are you reading data into itemName twice? I think you meant to read into itemCount first before itemName by the looks of your file format, thus you should eliminate the first line shown above and just have:
myFile >> itemCount >> itemName >> itemPrice >> totalPrice;
In terms of adding to the existing data if the farm name appears more than once, your current code overwrites the data from each line after printing and continuing to the next iteration of the while loop. Thus, you would have to redesign your code to save previous values from farms and check if the farm appears more than once and determine what to do from there.
Could use regex:
std::string line;
std::regex r{R"(([^,]*), ?([^ ]*) ([^ ]*) ([^ ]*) (\d*.?\d*))"};
std::smatch m;
while(getline(myFile, line)){
std::regex_match(line, m, r);
std::string farmName { m[1] };
int itemCount {std::stoi(m[2])};
std::string itemName { m[3] };
double itemPrice {std::stod(m[4])};
double totalPrice {std::stod(m[5])};
std::cout << farmName << " " << itemCount << " items contributed totaling $" << totalPrice << std::endl;
}
I have the txt file which contains for example:
Arthur 20
Mark 21
Josh 12
The are no empty lanes between, its only for readability!
What I want to do is write it on the screen in the same way as it is in the file.
I tried to make it this way:
ifstream file;
string word;
file.open("data.txt");
while(!file.eof()){
file >> word;
if(file.fail())
break;
cout << word << " ";
file >> word;
cout << word << endl;
}
But the output is:
Arthur 20
Mark 21
Josh 12
0
So why this 0 is being caught as a empty line to my string variable? I thought that fail() should stop the loop and leave me with correct output?
as long as you have names which don't contain white spaces and age as integer then you can read name as a string and age as an integer.
you don't need to check whether the file was successfully opened or not you can just abbreviate the operation:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream file;
std::string word;
int age;
file.open("data.txt");
while( file >> word)
{
file >> age;
std::cout << word << " " << age << std::endl;
}
std::cout << std::endl;
return 0;
}
if you want to use one variable and for sure a string one then:
while( file >> word)
{
std::cout << word << " ";
file >> word;
std::cout << word << std::endl;
}
I don't see any good thing to read age as a string and maybe later convert it back to an integer!
the output:
Arthur 20
Mark 21
Josh 12
Data in the input file:
Wilson Jack 87236.45 11
My code:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
ofstream out;
ifstream in;
string Lastname, Firstname;
double salary;
int increase;
in.open("Lab5_Ex_3_Input.txt");
out.open("Lab5_Ex_3_Output.txt");
in >> Lastname >> Firstname >> salary >> increase;
out << "Lastname: "<< Lastname << "Firstname " << Firstname << "salry :" << salary <<"increase: "<< increase <<endl;
in.close();
out.close();
return 0;
}
So, when I check the output file I am getting:
Lastname: Firstname salry :-9.25596e+061increase: -858993460
what am I doing incorrectly?
Try this:
if (!(cin >> value >> value2 >> value3)) {
cout << "input failed" << endl;
return -1;
}
My guess is that your input fails. You could also check if the file was opened correctly at all, which your code is missing.
BTW: There's no need to explicitly close the streams, they are closed automatically when they go out of scope and their destructor is called.
Your program is likely having trouble reading the input file. Why? Based on the output values:
Lastname: Firstname salry :-9.25596e+061increase: -858993460
This is due to the fact that both Lastname and Firstname are empty (i.e. there is nothing after the colon), that the numbers following salry and increase is common when you've uninitialized your variables as you've done in your code.
What you should do is check to see if the file is open:
if (!in.is_open()) {
std::cerr << "Error opening input file!\n";
exit(1);
}
I can't figure out why this won't read from my file...
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
int main()
{
int acctNum;
int checks;
double interest;
double acctBal;
double monthlyFee;
const int COL_SZ = 3;
ifstream fileIn;
fileIn.open("BankAccounts.txt");
if(fileIn.fail())
{
cout << "File couldn't open." << endl;
}
else
{
cout << left;
cout << "Bank Account records:" << endl;
cout << setw(COL_SZ) << "Account#" << setw(COL_SZ) <<
"Balance" << setw(COL_SZ) << "Interest" << setw(COL_SZ) << "Monthly Fee" << setw(COL_SZ) <<
"Allowed Checks" << setw(COL_SZ) << endl;
while(fileIn >> acctNum >> acctBal >> interest >> monthlyFee >> checks)
{
cout << setw(COL_SZ) << acctNum << setw(COL_SZ) << acctBal << setw(COL_SZ) << interest << setw(COL_SZ) <<
monthlyFee << setw(COL_SZ) << checks << endl;
}
}
fileIn.close();
system("pause");
return 0;
}
I took out the ios::out and put in ios::in same thing happened no data and the same thing with taking ios out all together. I did make the file from a previous program...would i have to put the reading of the files code into that program?
Edit
Looking at your input you can't read such complex input with just
while(fileIn >> acctNum >> acctBal >> monthlyFee >> checks)
This code is setup to read data formatted in the following form:
11 12.12 11.11 13.13 14.12
11 12.12 11.11 13.13 14.12
11 12.12 11.11 13.13 14.12
Instead you'll have to read the various strings and such before scraping out the data you need. For example to skip over the word "Account" below, you can read it into a dummy string
Account Number#1234
std::string dummy;
fileIn >> dummy; // read up to the whitespace,
// in this case reads in the word "Account"
Then To get the number you'll have to read the next string and extract the #1234
std::string temp;
fileIn >> temp; // read up to the whitespace,
// in this case reads in the word "Number#1234"
But you could also use getline to read up to and including the #
std::getline(fileIn, dummy, '#');
Then read in the number after the #
int acctNum = 0;
fileIn >> acctNum;
So if you're input is truly formatted as you describe, you'll have to spend a lot more time figuring out how to parse your data then you may have expected. I don't know enough about how your input is expected to give you a complete answer, but the above should hopefully get you started.
(Optionally, you could learn about regular expressions, but at this point you may just want to learn the basics.)
Original
I just tried your code out and with enough well-formatted values in the input, it works in g++. However, one thing that I am wary of looking at your code is this line:
while(fileIn >> acctNum >> acctBal >> monthlyFee >> checks)
If any of the above fails to read due to the file ending prematurely, your cout isn't going to get executed, causing no output to the screen. Does your input have all the above values? Are they well formatted? To debug I might try breaking up the reads:
while (fileIn)
{
fileIn >> acctNum;
std::cout << "Acct num is:" << acctNum << std::endl;
...
}
or just step through with a debugger.
For example for this input:
11 12.12 11.11 13.13 14.12
your code prints out
Bank Account records:
Account#BalanceInterestMonthly FeeAllowed Checks
11 12.126.93517e-31011.1113 `
But screwing with the input and adding a random non numeric character somewhere, ie:
11 * 12.12 11.11 13.13 14.12
causes me to get just
Bank Account records:
Account#BalanceInterestMonthly FeeAllowed Checks
So I would definitely look piece-by-piece at what's getting read and where a read from fileIn is failing, this would definitely cause your problems.
You know of course to remove the ios::out as specified here
You have
fileIn.open("BankAccounts.txt", ios::out);
^^^^^^^^
You're opening the file for output. Try ios::in.