looping through lines of a .txt file in C++ - c++

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.

Related

C++ Array not taking correct input from file

Disclaimer: I am a beginner to programming, so what I say might sound really stupid
I have to make a "Telephone Directory" for school. The program isn't complete, but there are some things that I need to fix before moving on. The array TelephoneNumbers either isn't storing the numbers from the file correctly, or isn't displaying them. For the SeaerchRecords function, the first number in the file is displayed correctly, the second is displayed as "2147483647," and the rest of the numbers display as "0." The modify function also doesn't change the number, and I confirmed this with the while in the function. The string array works perfectly fine, however. May someone explain what I'm doing incorrectly?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string TelephoneNames[100];
int TelephoneNumbers[100];
void ModifyRecords(); //Function to Modify Records
void SearchRecords(); //Function to Search Records
void DeleteRecords(); //Function to Delete Records
int main()
{
fstream inputFile;
fstream outputFile;
char choice;
inputFile.open("Telephone Names.txt"); //To store
for (int count=0;count<100;count++) //file names
{ //into a
inputFile >> TelephoneNames[count]; //string
}
inputFile.close();
inputFile.open("Telephone Numbers.txt");//To store
for (int count=0;count<100;count++) //file #'s
{ //into a
inputFile >> TelephoneNumbers[count];//string
}
inputFile.close();
//Display options available
cout << " Hello, do you want to:\n";
cout << " ======================\n";
cout << "-Modify Records|Enter M\n";
cout << "-Search Records|Enter S\n";
cout << "-Delete Records|Enter D\n";
//Store choice
cin >> choice;
//Send to different function
if (choice=='M'||choice=='m')
{
ModifyRecords();
}
if (choice=='S'||choice=='s')
{
SearchRecords();
}
return 0;
}
void ModifyRecords()
{
string name;
string newname;
int newnumber;
int count=0;
cout << "Enter the name of the person: ";
cin >> name;
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
}
cout << "Enter the new name of the person: ";
cin >> newname;
cout << "Enter the new number of the person: ";
cin >> newnumber;
TelephoneNames[count]={newname};
TelephoneNumbers[count]={newnumber};
count=0;
while (count<6)
{
cout << TelephoneNames[count] << endl;
cout << TelephoneNumbers[count] << endl;
cout << endl;
count++;
}
}
void SearchRecords()
{
string name;
int count=0;
cout << "Enter the name of the person you would like to find: ";
cin >> name;
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
}
cout << "Name: " << TelephoneNames[count] << endl;
cout << "Number: " << TelephoneNumbers[count] << endl;
}
Since there is no any answer still and I don't see exactly the problem at this point I'll provide some suggestions how you can find a problem in your code.
In any programming situation when you can't find a bug, first task is to locate it as much precisely as you can and check all input data and assumptions. Usually, debugger is used for such purposes, but you can just output text in console before creating final version of your program.
To start with, you must check that you really received names and telephones from your file:
inputFile.open("Telephone Names.txt"); //To store
for (int count=0;count<100;count++) //file names
{ //into a
inputFile >> TelephoneNames[count]; //string
cout << TelephoneNames[count] << endl; //WE MUST SEE WHAT IS REALLY STORED IN TelephoneNames
}
inputFile.close();
inputFile.open("Telephone Numbers.txt");//To store
for (int count=0;count<100;count++) //file #'s
{ //into a
inputFile >> TelephoneNumbers[count];//string
cout << TelephoneNumbers[count] << endl; //WE MUST SEE WHAT IS REALLY STORED IN TelephoneNumbers
}
inputFile.close();
Ok, when it is checked and you are defenitely sure there is no problem in your data we can move to SeaerchRecords function doing the same procedure. We must check what is happening while you are searching:
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
cout << "Search step: " << count << " name " << name << " found name " << TelephoneNames[count] << " number " << TelephoneNumbers[count] << endl;
}
Doing so you will locate your bug rather quickly. The problem can be in input files format, in difference of "name" and stored names format etc.
I'll provide several additional suggestion how you can improve your code.
1) Try to use const declarations for such commonly used things as number of records (const int NUMBER_OF_RECORDS = 100; insted of just putting '100' everywhere), it will reduce the amout of work and possible bugs. 2) Try to check all possible problems that you program can encounter if someting is wrong with data. What will happen if you have less than 100 records in your files now? Program crush or silent reading of unappropriate data which is even worse. Check that you haven't reach file end on any step of reading along with current check that you've reached you number of records and do something in case of unappropriate data.
3) Check the possible problems with conditions in your cycles not to run them infinite number of times. Now your condition for(count=0;TelephoneNames[count]!=name;count++)
will execute forever if there is no such name or just crush the program on count 100 or more. You should check that count doesn't exceed that value. Good luck!

Using nested loops and fin correctly

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.

deleting line in linux text file with C++

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.

Reading a particular word in .txt file

I have a txt file which contains the name and roll number of students. I want to read and display a particular roll number from his file. It shows only the first roll number, but I want to read the roll number of the 2nd person.
That is, if I want to read the roll number of "ss", it shows the roll number of the first person
The program is
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
void student_read()
{
clrscr();
char name[30], n[30], temp[30];
int i, roll_no, code, count=0;
ifstream fin("tt.txt",ios::in|ios::beg);
if(!fin)
{
cout << "cannot open for read ";
return;
}
cout << "Enter the name of student" << "\n";
cin >> n;
while(fin >> name >> roll_no)
{
cout << roll_no << endl;
}
if(string[name] == string[n])
{
cout << "roll no" << "\n" << roll_no;
}
else
cout << "Not found";
}
void main()
{
clrscr();
cout << "Students details is" << "\n";
student_read();
getch();
}
The txt file contains this data:
sourav
123
ss
33
Does you have end of each line in your text file? Does you have sourav 123 ss 33 or sourav 123\nss 33?And this if(n[30]==name[30]) compare only 1 character in string.
You're doing the output of what is in the file already before you even input the name to search for.
Reorder your statements, like this:
cout<<"Enter the name of student"<<"\n";
cin>>n;
while(fin>>name>>roll_no)
{
//...
Also, if you only want to output one name and roll_no, in your loop, you have to check some kind of condition whether to print or not. At the moment, your code should actually print the roll_no of all rows in the file, and possibly sometimes the last one twice.
So the condition you have after the input belongs into the loop.
Additionally, however, you're only comparing the 31st character of the char array (which is actually already out of the bounds of your array variables! Their indices go from 0..29, i.e. even if you allocated a 30 characters array, the ). That means, your condition will be true if the next to last character matches. This place will most likely not be initialized yet, so you compare basically gargabe values and will get unexpected/random results.
If you want to, as the description suggests, want to compare the whole char array, that works differently by the way (not with the == operator, that would only compare pointer addresses), you'd need to use the strcmp function. But even better would be to use std::string instead of char *.
void student_read()
{
clrscr();
std::string name, n, temp;
int i, roll_no, code, count = 0;
std::ifstream fin("tt.txt", ios::in | ios::beg);
if (!fin)
{
std::cout << "cannot open for read ";
return;
}
std::cout << "Enter the name of student" << "\n";
std::cin >> n;
while (fin >> name >> roll_no)
{
std::cout << roll_no << std::endl;
}
if (name == n)
{
std::cout << "roll no" << "\n" << roll_no;
}
else
std::cout << "Not found";
}
int main()
{
clrscr();
std::cout << "Students details is\n";
student_read();
getch();
}

Use ifstream to read a text file with random generated numbers in columns and find the minimum and maximum from the list?

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.