I have a question about using fin and loops correctly in C++. I have a file I read from that has 78 lines of data consisting of a ski resort name, its elevation, and then 12 numbers that are the monthly precipitation. The program is supposed to read from that file then output to a different file the name, elevation, and the average annual precipitation. For some reason I can't get the average to work right. I have to have one loop run for each of the 78 lines, then a nested loop run to process each of the 12 months.
I also have to use a cin.ignore that I don't know where to put.
Code:
int main() {
ifstream fin("../Debug/monthlyPrecipitation.txt");
if (fin.fail())
{
cout << "Error opening file." << endl;
}
ofstream fout;
fout.open("../Debug/annualPrecipitation.txt", ios::app);
int elevation;
const int MONTHSPERYEAR = 12;
double average, precipTotal, precip;
string stationName;
fout << "Annual Precipitation Report" << endl;
fout << endl;
fout << "Weather Station" << setw(18) << "Elevation" << setw(12) << "Precipitation" << endl << endl;
for (int counter = 1; counter <= 78; ++counter)
{
getline(fin, stationName, '\t');
fin >> elevation;
for (int counter = 1; counter <= 12; ++counter)
{
fin >> precip;
precipTotal = precipTotal + precip; //the issue is here
}
average = precipTotal / MONTHSPERYEAR;
fout << stationName << setw(22) << elevation << setw(12) << average << endl;
}
Thanks.
Along with contaminating precipTotal, It looks like you're forgetting to turn the line into a stringstream. I'm assuming that a line in your file looks like:
Resort_Name elevation precip1 precip2 ... precip12
if you get that line, then you're grabbing all the precips along with it, and then when you fin in the inner loop, you're reading in the next line. What you need to do is get that line, and turn it into a stringstream. Then, read in the resort name into a different string, the elevation into an int, and then calculate the average without contaminating the total.
You're not clearing precipTotal before the inner loop, thus contaminating the average of a given station with the results of the previous ones.
You don't initialize all the POD variables such as elevation, average, precipTotal, and precip.
However, only precipTotal has an issue because the others have new value in the loop.
Related
Total C++ beginner and as the title says, i'm trying to read a .txt file looping through line by line whilst performing a calculation on the data of the line before moving to the next line.
int main() {
ifstream in_file;
string name;
int kiloWatt{};
int amperage{};
int cores{3};
int voltage{480};
double powerFactor{0.8};
double efficiency{0.93};
double root{};
in_file.open("../test.txt");
if(!in_file){
cerr <<"Problem opening file" << endl;
return 1;
}
while (in_file >> name >> kiloWatt){
root = sqrt(cores);
amperage = (kiloWatt*1000)/(root*voltage*powerFactor*efficiency);
cout << setw(10) << name
<< setw(10) << kiloWatt
<< setw(10) << amperage
<< setw(10) << root
<< endl;
}
in_file.close();
return 0;
}
this works however it closes the loop after the first line and so displays only one line.... anyone point me in the direction of why? Many thanks.
The txt file its referencing would look something like:
name1 23.5
name2 45.6
name3 234.8
kiloWatt is an int, so on the first line, it'll read 23, see a non-integer character and stop. The next name will be ".5", and you'll try to read "name2" into kiloWatt, which will fail, since it's not a number--breaking your loop.
Change kiloWatt to be a double to fix this.
I am fairly new to this site, and programming in not my strong suit, so I apologize if the way I word things are hard to follow. Below is a code I have written to calculate the odds of profiting from playing lottery scratchers. It is suppose to output the results to a .txt file. I am able to get it to output to that file, and the everything in the output file is correct, except for the name of the second game. It is missing a whole word. How my output file looks is shown below.
Game Cost Odds
-----------------------------------------------
SMALL BEANS $ 1 1 in 1.67
BOOTY, ARRR $ 10 Not possible
MONEY HU$TLA$ $ 20 1 in 99.80
The second and third games both have a space before they start, and I am not sure why. Also, the second game is suppose to say "Pirate's Booty, Arrr." I do not understand how a whole word is missing. Any help on how to fix this would be very much appreciated. My code is below.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
// Declaring Variables
int Profit; // The lowest dollar amount you want to profit
int CostOfTicket; // The cost of the ticket in the dollar amount
int NumberOfPrizes; // The number of possible prizes that can be won
int PrizeValue; // The value of the prize in dollars
int NumberOfTickets; // The total number of tickets that were printed with that prize
int TicketsNotClaimed; // The number of tickets with that prize that have not yet been claimed
double RemainingTickets; // Total number of tickets that are remaining
double RemainingTicketsForProfit; // The total number of tickets for a profit that are remaining
double Odds; // The odds of winning the game
string game; // The name of each game that can be played
string output; // The name of output file the user chooses (.txt)
// Open the input text file
ifstream inputfile ("scratcher.txt"); // Open the input file called "scratcher.txt"
// The program will ask the user to enter the lowest amount they would like to profit by when playing one of the lottery games.
// The games include "Small Beans," "Pirate's Booty, Arrr," and "Big Money Hu$tla$."
cout << "Enter the lowest dollar amount that you would like to profit: ";
cin >> Profit;
cout << "Enter the output file name: ";
cin >> output; //name of output file user chooses
ofstream outputfile (output.c_str()); //creates an output file with the name user chose for output
cout << "Generating report...";
// How the output will be formatted
outputfile << left << setw(25) << "Game" << setw(10) << "Cost" << setw (10) << "Odds" << endl;
outputfile << "-----------------------------------------------" << endl;
// Reads the name of the game
while (getline(inputfile, game))
{
inputfile >> CostOfTicket; // Reads the cost of the ticket
inputfile >> NumberOfPrizes; // Reads the number of prizes
RemainingTickets = 0;
RemainingTicketsForProfit = 0;
for (int i = 0; i < NumberOfPrizes; i++)
{
inputfile >> PrizeValue; // Reads the value of the prize
inputfile >> NumberOfTickets; // Reads the total number of tickets
inputfile >> TicketsNotClaimed; // Reads the number of tickets that are not claimed
RemainingTicketsForProfit = RemainingTicketsForProfit + TicketsNotClaimed;
// The next line will compute a sum of the number of the remaining tickets where the user would profit
if (PrizeValue > Profit)
{
// The following line computes the running sum of the number of tickets remaining for that game.
RemainingTickets = RemainingTickets + TicketsNotClaimed;
}
}
// Tells the program what to do if there are no tickets remaining
if (RemainingTickets == 0)
{
// Formats the output
outputfile << left << setw(25) << game << setw (2) << "$" << CostOfTicket << right << setw(15) << "Not possible" << endl;
}
else
{
// Tells the program to calculate the odds.
Odds = RemainingTicketsForProfit / RemainingTickets;
outputfile << left << setw(25) << game << setw (2) << "$" << CostOfTicket << right << setw(15) << "1 in " << setprecision(2) << fixed << Odds << endl;
}
string blankLine;
inputfile >> blankLine;
}
// Closes the input and output text file
inputfile.close();
outputfile.close();
return 0;
}
string blankLine;
inputfile >> blankLine;
Not sure why you did this but it's eating up the first word of your next line.
Remember, operator>> into a string skips whitespace then eats precisely one word.
Whatever you're trying to do regarding skipping blank lines, this is not how to do it!
i need help in how i should write a code for doing a delete line using c++ in linux. what i have in the text file is listed below
description:amount:date
electricity bill:100:25jan2015
telephone bill:100:25jan2015
telephone bill:50:25jan2015
i want to do it so that when the user selects option b to remove the expense that the user input and to prevent the program from deleting duplicate data the user will have to input the amount and date. thank you.
and the temp.txt is used to store what was not deleted before being renamed to Expense.txt so if telephone bill value 100 was removed it would become
electricity bill:100:25jan2015
telephonebill:50:25jan2015
void deleteexpensesdata(string& expense, string& texpense, double& amount, string& date){
int check, x=0;
ifstream Expenses("Expense.txt");
ofstream temp("temp.txt");
cout << "\n";
cout << "Enter Type of Expense you wish to remove" << endl;
cin >> texpense;
while(Expenses >> expense >> amount >> date){
if(texpense!=expense){//if there are expenses with different name, input their data into temp file
temp << expense << ":" << amount << ":" << date <<endl;
}
if(texpense==expense){// if user entered correct name, x=1 for later output message that the user data has been deleted
x=1;
}
}
Expenses.clear();
Expenses.seekg(0, ios::beg);
Expenses.close();
temp.close();
remove("Expense.txt");
rename("temp.txt","Expense.txt");
if(x==0){//x was set to 0 at start, so if it didn't change, it means there is error
cout << "Remove of Expense failed" << endl;
}
else{//if x is not = 0 then remove is successful
cout << "Expenses has been removed" << endl;
}
}
the code that calls the function is below
cout << "Remove Expense.\n";
deleteexpensesdata(expense, texpense, amount, date);
cout << "Expense Date has been delete. \n" << endl;
cin.ignore();
cin.get();
This code below gets the user input and converts the double to string and turns all 3 variable into line with the delimiter ":" as seen in your example input and after u open the file u get the line that does not match into a temp file and rename the file essentially removing it.
double expamt;
string line, expdesc, exptrans;
cout << "Please Enter Expense: \n";
cin >> expdesc;
cout << "Please Enter Amount: \n";
cin >> expamt;
string newamt = static_cast<ostringstream*>( &(ostringstream() << expamt) )->str();
cout << "Date of Transaction: (e.g 20jan2015)\n";
cin >> exptrans;
string input = expdesc + ":" + newamt + ":" + exptrans;
ifstream myfile;
ofstream tempfile;
myfile.open("Expense.txt");
tempfile.open("temp.txt");
while (getline(myfile, line))
{
if (line != input)
tempfile << line;
}
cout << "\nExpense " << expdesc << " has been removed \n" <<endl;
myfile.close();
tempfile.close();
remove("Expense.txt");
rename("temp.txt", "Expense.txt");
First an advice: You should learn to use gdb.
Your code has several logic errors, for instance the line:
Expenses >> expense >> amount >> date
might not be doing what you're expecting to do, since the operator >> don't deal (by default) with character ':' as a separtor or delimiter.
Also, don't use a variable (x) for checking input errors, ifstream and ofstream objects has functions like: ifstream::good, ifstream::fail and ifstream::bad.
However you could user a x for check if any change was made, if not you don't need the file operations:
remove("Expense.txt");
rename("temp.txt","Expense.txt");
Said that, your comment con be readed:
x was set to 0 at start, so if it didn't change, it means there is error
Actually that's wrong, x == 0 also means the condition texpense==expense never got true.
Recomendations
You could use std::iftream::getline and change the delimiter to :.
You could use std::iftream::getline combined with regex and std::regex::search.
I think the first is easier (if : aren't sorrounded by spaces), the second is more elegant as less error prone. Is up to you.
I am creating a school project but seems lost at the moment. Can someone help me figure out my problem? Here's what's going on:
I have a program that outputs a random generated numbers in a text file using ofstream. It is generated with a format of two columns (one column is SalePrice & the second column RegularPrice). My problem is creating a code that will do the following:
Create a function that will read the text file generated by the first program
Find the average of the second column ONLY! (Regular Price) then outputs it in the screen
Find the minimum and maximum of the second column ONLY! (Regular Price) then outputs it in the screen
Please help! I need help how to code the ifstream part, I am new to C++ and have tried all the solutions in many books but doesn't seem to work for my needs? :-( Any help will be greatly appreciated! Thanks in advance!
Here's just the section of my code (not the entirety), it is not giving me an error . . . it is simply not giving me anything:
float SalePrice[userInput];
float RegularPrice;
string cPrice;
string readFile;
int count = 0;
ifstream inputFile;
inputFile.open(fileName);
inputFile >> RegularPrice;
// To get you all the lines and place the line from myfile into the line variable
while(!inputFile.eof() && getline(inputFile, readFile))
{
if (count < userInput)
{
inputFile >> readFile;
readFile += cPrice; // Saves the line in STRING.
//display the line we gathered:
cout << cPrice << endl;
}
++count;
}
avgRPrice = RegularPrice / userInput;
cout << endl;
cout << fixed << setprecision (2);
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
EDITED:
Here's my current code for finding the max & min:
int maxRPrice(float RPrice[])
{
if (RPrice > maxRPrice)
maxRPrice = RPrice;
return maxRPrice;
}
int minRPrice(float RPrice[])
{
if (RPrice < minRPrice)
minRPrice = RPrice;
return minRPrice;
}
Here is an improved version of your code which works perfectly for me:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int userInput = 2;
float SalePrice[userInput]; //Make an array
float RegularPrice[userInput]; //Make an array
string readFile;
ifstream inputFile;
inputFile.open("yourFile.txt");
if(!inputFile){ //Check wether the file is open
cout<<"Couldn't open file!" << endl;
return -1;
}
// To get you all the lines and place the line from myfile into the line variable
for(int count = 0; !inputFile.eof() && (count < userInput) ; ++count) //Why are you using a while-loop if you need to count the iterations
{
//
inputFile >> SalePrice[count] >> RegularPrice[count]; //loads column SalePrice/RegularPrice into the array at position 'count'
}
float sumRegularPrice = 0;
for(int i=0; i < userInput; i++)
sumRegularPrice += RegularPrice[i];
float avgRPrice = sumRegularPrice / userInput;
cout << endl;
cout << fixed;
cout << "The average of all the Regular Prices in the file is: " << avgRPrice << endl;
//cout << "The minimum Regular Price in the file is: " << minRPrice << endl;
//cout << "The maximum Regular Price in the file is: " << maxRPrice << endl;
system("pause");
return 0;
}
Why are you loading RegularPrice only once? As far as I got your explanation about the file format (you said one column is SalePrice & the second column RegularPrice), every line might have this content:
3.44 5.99
To get the min and max price you can simply write two functions.
With this input:
3.44 5.99
5.54 8.99
I get this output (in the console):
The average of all the Regular Prices in the file is: 7.490000
If you have some questions don't hesitate to ask me.
The program I code below should
List all payment made by each student, show amount paid and outstanding
I need some help with the following section:
void payment()
{
// Display message asking for the user input
std::cout << "List all payment made by each student, show amount paid and outstanding." << std::endl;
// Read from text file and Display list of payment
std::ifstream infile; // enable to open, read in and close a text file
float StudentCode; // to store the student enrolment number
float Amount; // to store the amount of money
float Type; // to store information on type of payment made
float Outstanding; // to store amount of money is due
infile.open("Payment.txt"); // open a text file called Payment
if (!infile)
{
std::cout << "Item list is empty" << std::endl; // if the file is empty it output the message
}
else
{
std::cout << "List of Payment: " << std::endl;
std::cout << "" << std::endl;
std::cout << "Enrolment No." << "Amount" << "Outstanding" << std::endl;
// If there is Student Code that has the same number, it need to combined the amount it paid
// For an example
// Student Code: 12 Amount: 25
// Student Code: 12 Amount: 50
// so it should display the following when the program runs:
// Student Code: 12 Amount: 75
while(!infile.eof()) // output the description of the text file onto the screen
{
getline(infile,StudentCode,Amount);
Outstanding = Amount - 100;
std::cout << StudentCode << Amount << "$" << Outstanding << std::endl;
//iter++;
}
std::cout << "End of list\n" << std::endl;
}
infile.close(); // close the text file
}
What is wrong with the getline part:
getline(infile,StudentCode, Amount);
Also the program should not display repeated Student Code but combine the amount it paid.
Where I explain in the comment section
// If there is Student Code that has the same number .....
How do I do this?
getline reads a line from a stream into a string. What you're trying to do, is more like this
while (infile >> StudentCode >> Amount) {
// process values
}
If you want to sum up all amounts, you must first accumulate and afterwards loop through the collected values and print them
std::map<int, float> amountsPaid;
int studentCode;
float amount;
// accumulate amounts
while (infile >> studentCode >> amount) {
amountsPaid[studentCode] += amount;
}
// loop through map and print all entries
for (auto i = amountsPaid.begin(); i != amountsPaid.end(); ++i) {
float outstanding = i->second - 100;
std::cout << i->first << ": " << i->second << "$, " << outstanding << '\n';
}
There are several problems here. One is that getline reads one line of text into a single std::string variable, not multiple float fields.
For that you might try
infile >> StudentCode >> Amount;
A second problem is that
while(!infile.eof())
will not check if the next input is going to work but if the previous input attempt failed beause it reached end-of-file.
The standard method is to combine these into
while (infile >> StudentCode >> Amount)
{
// do something with the code and amount
}
Your call to getline doesn't seem correct.
The documentation states
istream& getline ( istream& is, string& str, char delim );
But your giving it
getline(istream&, float, float);
You should be trying to read the line as a string and then parse out the 2 floats.
Since your using c++, if the file is well formatted you could just redirect cin and it'll be easier. You could just do something like
while (infile >> StudentCode) {
infile >> Amount;
}