This is my text file:
12345 shoe 5 0
34534 foot 72 1
34562 race 10 0
34672 chicken 24 150
88 pop 65 0
I need to take this file and go row by row, assign the first number as an identifier itemNum, second word as itemName, third number as itemPrice, and last number as itemAdjusmentValue. I will need to perform arithmetic with the last two numbers itemPrice and itemAdjusmentValue.
Code so far:
using namespace std;
// making a struct to store each value of the cuadre
struct Cuadre
{
int itemNum;
string itemName;
int itemPrice;
int itemAdjusment;
};
int main (){
ifstream infile("sheet_1.txt");
string checkLine;
if (infile.is_open()){
while ( infile.good()){
getline (infile, checkLine);
cout << checkLine << endl;
}
}
else
cout << "error with name of file" << endl;
vector<Cuadre> procedures;
Cuadre line;
while(Cuadre >> line.itemNum >> line.itemName >> line.itemPrice >> line.itemAdjusment){
procedures.push_back(line);
}
This code generates an error on the last while statement
expected primary-expression before '>>' token
I cant really find a specific tutorial on how to do this, and i've looked a good amount.
From the code you posted, (with reference to the >> istream operators) it looks like you want to stream the contents of the string data read from your file into the members of a struct.
It is not possible to stream directly from a std::string (eg: checkLine >> x >> y >> z), as string does not provide a streaming interface.
In order to do that you need to use a stream, such as std::stringstream.
You could populate a with your string checkLine, and then stream from that into your data members
std::stringstream ss(checkLine);
ss >> line.itemNum >> line.itemName >> line.itemPrice >> line.itemAdjusment;
Example code:
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
// making a struct to store each value of the cuadre
struct Cuadre
{
int itemNum;
string itemName;
int itemPrice;
int itemAdjusment;
};
int main (){
ifstream infile("sheet_1.txt");
string checkLine;
vector<Cuadre> procedures;
if (infile.is_open()){
while ( infile.good()){
getline (infile, checkLine);
cout << checkLine << endl;
Cuadre line;
std::stringstream ss(checkLine);
ss >> line.itemNum >> line.itemName >> line.itemPrice >> line.itemAdjusment;
procedures.push_back(line);
}
}
else
cout << "error with name of file" << endl;
return 0;
}
You need to push into the vector inside the loop that reads from the file. And you should be getting the fields from checkLine -- Cuadre is a type name, not a variable you can read from. But to do that you need to create a stringstream.
int main (){
ifstream infile("sheet_1.txt");
string checkLine;
vector<Cuadre> procedures;
if (infile.is_open()){
while (getline (infile, checkLine)){
Cuadre line;
cout << checkLine << endl;
stringstream linestream(checkline);
if (linestream >> line.itemNum >> line.itemName >> line.itemPrice >> line.itemAdjusment) {
procedures.push_back(line);
} else {
cout << "incorrect line" << endl;
break;
}
}
}
else {
cout << "error with name of file" << endl;
}
}
while (infile.good()) is also not correct, it's essentially the same as while (!infile.eof()). See Why is iostream::eof inside a loop condition considered wrong?
You can try reading directly into struct as well:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
struct Cuadre
{
int itemNum;
std::string itemName;
int itemPrice;
int itemAdjusment;
};
int main()
{
std::vector<Cuadre> procedures;
std::ifstream infile("sheet_1.txt");
while (infile)
{
Cuadre line;
if (infile >> line.itemNum >> line.itemName >> line.itemPrice >> line.itemAdjusment)
procedures.push_back(line);
else
break;
}
if (!procedures.empty())
{
for (auto &p : procedures)
std::cout
<< "itemNum: " << p.itemNum << "\t"
<< "itemName: " << p.itemName << "\t"
<< "itemPrice: " << p.itemPrice << "\t"
<< "itemAdjusment: " << p.itemAdjusment
<< std::endl;
}
else
std::cout << "error with file or data" << std::endl;
return 0;
}
Prints:
itemNum: 12345 itemName: shoe itemPrice: 5 itemAdjusment: 0
itemNum: 34534 itemName: foot itemPrice: 72 itemAdjusment: 1
itemNum: 34562 itemName: race itemPrice: 10 itemAdjusment: 0
itemNum: 34672 itemName: chicken itemPrice: 24 itemAdjusment: 150
itemNum: 88 itemName: pop itemPrice: 65 itemAdjusment: 0
If you define an overload of >> for your type Cuadre, you can read directly from the file into Cuadre objects.
std::istream& operator>>(std::istream& is, Cuadre & cuadre)
{
std::string s;
getline(is, s);
std::cout << s;
std::stringstream ss(s);
ss >> cuadre.itemNum >> cuadre.itemName >> cuadre.itemPrice >> cuadre.itemAdjusment;
return is;
// or without logging
return is >> cuadre.itemNum >> cuadre.itemName >> cuadre.itemPrice >> cuadre.itemAdjusment;
}
int main (){
ifstream infile("sheet_1.txt");
vector<Cuadre> procedures;
for (Cuadre line; infile >> line;) {
procedures.push_back(line);
}
// or with #include <algorithm>
std::copy(std::istream_iterator<Cuadre>{ infile }, {}, std::back_inserter(procedures));
}
Related
#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;
void check(ifstream &iFile)
{
if (!iFile.is_open())
{
cout << "Data file not found!" << endl;
system("pause");
exit(1); // exit the program if the file is not found.
}
}
void readIn(ifstream &iFile, vector<string> &fName, vector<string> &lName, vector<string> &jTitle, vector<string> &eID, vector<double> &hoursWorked, vector<double> &wage, vector<int> &deductions, vector<double> &sPay, string sTemp, double dTemp, int iTemp)
{
while (!iFile.eof())
{
iFile >> sTemp;
fName.push_back(sTemp);
iFile >> sTemp;
lName.push_back(sTemp);
iFile.ignore();
getline(iFile, sTemp);
jTitle.push_back(sTemp);
iFile >> sTemp;
eID.push_back(sTemp);
iFile >> dTemp;
hoursWorked.push_back(dTemp);
iFile >> dTemp;
wage.push_back(dTemp);
iFile >> iTemp;
deductions.push_back(iTemp);
iFile >> dTemp;
sPay.push_back(dTemp);
}
cout << "completed" << endl;
}
int main()
{
ifstream iFile;
iFile.open("data.txt");
check(iFile);
vector<string> fName, lName, eID, eStatus, jTitle;
vector<double> nPay, gPay, oPay, oHours;
vector<double> hoursWorked, wage, sPay;
vector<int> deductions;
// temporary names to pass to the vector
string sTemp; // string temp
double dTemp=0; // double temp
int iTemp=0; // integar temp
readIn(iFile, fName, lName, jTitle, eID, hoursWorked, wage, deductions, sPay, sTemp, dTemp, iTemp);
/* while (!iFile.eof())
{
iFile >> sTemp;
fName.push_back(sTemp);
iFile >> sTemp;
lName.push_back(sTemp);
iFile.ignore();
getline(iFile, sTemp);
jTitle.push_back(sTemp);
iFile >> sTemp;
eID.push_back(sTemp);
iFile >> dTemp;
hoursWorked.push_back(dTemp);
iFile >> dTemp;
wage.push_back(dTemp);
iFile >> iTemp;
deductions.push_back(iTemp);
iFile >> dTemp;
sPay.push_back(dTemp);
}*/
int sizeOf = fName.size();
for (int a = 0; a < sizeOf; a++)
{
cout << fName.size() << " FName " << fName[a] << " LName " << lName[a] << " JobTitle " << jTitle[a] << endl;
cout << "EmployeeID " << eID[a] << " Hours Worked " << hoursWorked[a] << " Hourly Wage " << wage[a] << endl;
cout << "Deductions " << deductions[a] << " Salary Pay " << sPay[a] << endl;
}
system("pause");
return 0;
}
I'm running into an issue where my function will not do anything. It will compile, but there is no output. The thing is when I take out the vector sPay from all the parts it works perfectly fine. Any suggestions as to why that one part isn't working? From my limited knowledge it should work perfectly fine, however I can't figure out what would be causing this.
My example text file is
Alan
WakeField
IT GUY
T2034
40
15
1
Hourly
0.00
Your input file does not match your reading code. There are 9 values in the file that you have shown, but your code is attempting to read only 8 values.
When readIn() gets to this code:
iFile >> dTemp;
sPay.push_back(dTemp);
It attempt to read a double but the file has Hourly instead, so the read fails.
So, either remove the Hourly line from the file, or else add a call to iFile >> sTemp to read that line.
Also, the parameters string sTemp, double dTemp, and int iTemp should be declared as local variables instead of as input parameters.
Also, readIn() is not doing any error handling. Your main() code makes an invalid assumption that the vector of first names exactly matches the size of the other vectors, but readIn() does not guarantee that.
And lastly, checking eof() before you have read anything is wrong. The stream's eofbit flag is not updated until a read operation attempts to read past EOF.
You should consider re-writing this code. For example, try something more like this:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
struct Employee
{
std::string fName;
std::string lName;
std::string title;
std::string eID;
double hoursWorked;
double wage;
int deductions;
std::string wageType;
double sPay;
Employee() :
hoursWorked(0), wage(0), deductions(0), sPay(0)
{
}
};
void check(std::ifstream &iFile)
{
if (!iFile.is_open())
{
std::cout << "Data file not found or unable to open!" << std::endl;
std::system("pause");
exit(1); // exit the program.
}
}
void readIn(std::ifstream &iFile, std::vector<Employee> &employees)
{
std::ios_base::iostate oldstate = iFile.exceptions();
iFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
try
{
do
{
Employee emp;
iFile >> emp.fName;
iFile >> emp.lName;
std::getline(iFile, emp.title);
iFile >> emp.eID;
iFile >> emp.hoursWorked;
iFile >> emp.wage;
iFile >> emp.deductions;
iFile >> emp.wageType;
iFile >> emp.sPay;
employees.push_back(emp);
}
while (!iFile.eof());
}
catch (const std::ios_base::failure &)
{
std::cout << "Data file corrupted!" << std::endl;
std::system("pause");
exit(1); // exit the program.
}
iFile.exceptions(oldstate);
std::cout << "completed" << std::endl;
}
int main()
{
std::ifstream iFile("data.txt");
check(iFile);
std::vector<Employee> employees;
readIn(iFile, employees);
int sizeOf = employees.size();
for (int a = 0; a < sizeOf; a++)
{
std::cout << "FName " << employees[a].fName
<< " LName " << employees[a].lName
<< " JobTitle " << employees[a].title
<< std::endl;
std::cout << "EmployeeID " << employees[a].eID
<< " Hours Worked " << employees[a].hoursWorked
<< " << employees[a].wageType << " Wage " << employees[a].wage
<< std::endl;
std::cout << "Deductions " << employees[a].deductions
<< " Salary Pay " << employees[a].sPay
<< std::endl;
std::cout << std::endl;
}
std::system("pause");
return 0;
}
Alternatively, since your data is line-based, you should use std::getline() to read each line, and then use std::istringstream to parse values:
void readIn(std::ifstream &iFile, std::vector<Employee> &employees)
{
std::string sTemp;
std::ios_base::iostate oldstate = iFile.exceptions();
iFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
try
{
do
{
Employee emp;
std::getline(iFile, emp.fName);
std::getline(iFile, emp.lName);
std::getline(iFile, emp.title);
std::getline(iFile, emp.eID);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.hoursWorked))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.wage))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.deductions))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, emp.wageType);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.sPay))
iFile.setstate(std::ifstream::failbit);
employees.push_back(emp);
}
while (!iFile.eof());
}
catch (const std::ios_base::failure &)
{
std::cout << "Data file corrupted!" << std::endl;
std::system("pause");
exit(1); // exit the program if the file is corrupted.
}
iFile.exceptions(oldstate);
std::cout << "completed" << std::endl;
}
I went derp for a moment. I forgot to read in the hourly or salaried before going to salary pay.
I have to read in a .txt file that contains votes used to determine who would win a pretend election. Here is a little bit of the file so you can get an understanding.
1YYYYYYYYYYThe New Guy
2YNYNYNYNYNHarry Potter
2YNNYYNNYYNHarry Potter
2NNNNNNNNNNThe New Guy
3NYNYNYNYNYThe New Guy
3YYYYYYYYYYHarry Potter
3YYYYYYYYNYHarry Potter
The first number is the "ID" number and if their are any duplicates of that number I am not supposed to read it into the output.The list of number goes all the way up to 99 with duplicates scattered throughout the file as shown. The numbers are all in order though. So it can go 1222333 as shown but cant do 122332. Here is the code I have so far, the loop just stops when it hits the first duplicate, any help would be appreciated.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdio>
#include <string>
int main()
{
int ID; //pirate ID number
int IDTest;
char ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10; //vote on amendments
std::string vote; //vote for captain
std::ifstream fileReader; //open file for reading
fileReader.open("BallotsHogwart.txt");
if (fileReader.fail())
{
std::cout << "The ballots failed to open with code: " << fileReader.failbit;
}
else
{
do
{
IDTest = ID;
fileReader >> ID;
if (IDTest != ID)
{
std::cout << "Id:" << ID;
fileReader >> ch1;
fileReader >> ch2;
fileReader >> ch3;
fileReader >> ch4;
fileReader >> ch5;
fileReader >> ch6;
fileReader >> ch7;
fileReader >> ch8;
fileReader >> ch9;
fileReader >> ch10;
std::cout << " char 1 - 10: " << ch1 << ch2 << ch3 << ch4 << ch5 << ch6 << ch7 << ch8 << ch9 << ch10;
getline(fileReader,vote);
std::cout << " the votee: " << vote << std::endl;
}
} while(!fileReader.eof());
}
fileReader.close();
return 0;
}
You need to ignore the line when the ID is duplicated using getline()
The code will be like this:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdio>
#include <string>
int main() {
int ID = 0; //pirate ID number
int IDTest;
char ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10; //vote on amendments
std::string vote; //vote for captain
std::string ignore; //ignore
std::ifstream fileReader; //open file for reading
fileReader.open("asdas.txt");
if (fileReader.fail())
{
std::cout << "The ballots failed to open with code: " << fileReader.failbit;
}
else
{
do
{
IDTest = ID;
fileReader >> ID;
if (IDTest != ID)
{
std::cout << "Id:" << ID;
fileReader >> ch1;
fileReader >> ch2;
fileReader >> ch3;
fileReader >> ch4;
fileReader >> ch5;
fileReader >> ch6;
fileReader >> ch7;
fileReader >> ch8;
fileReader >> ch9;
fileReader >> ch10;
std::cout << " char 1 - 10: " << ch1 << ch2 << ch3 << ch4 << ch5 << ch6 << ch7 << ch8 << ch9 << ch10;
getline(fileReader, vote);
std::cout << " the votee: " << vote << std::endl;
}
else {
getline(fileReader, ignore);
}
} while (!fileReader.eof());
}
fileReader.close();
std::cin.get();
return 0;
}
I would use a map
std::ifstream fileReader; //open file for reading
fileReader.open("BallotsHogwart.txt");
if (fileReader.fail())
{
std::cout << "The ballots failed to open with code: " << fileReader.failbit;
}
else
{
string line;
std::map<string, string> myvotes;
do
{
getline(filereader, line);
// pull out ID
std::map<string,string>::iterator value = myvotes.find(ID);
if (value == myvotes.end())
continue;
// do the rest of your processing on line.
// put "Harry Potter" in map.
myvotes.insert(ID, candidate);
} while(!fileReader.eof());
fileReader.close();
return 0;
}
data file:
candy, 1.99, 26
chips, 2.55, 22
//my attempt to read in each line creating a new object for the line
while (getline(inFile, line, '\n')) {
istringstream ss(line);
ss >> name >> price >> amount;
products newProduct(name, price, amount);
item.push_back(newProduct);
}
Right now I am only getting the name and price of only the first line.
How can I read in the entire line storing all three values for all lines in the file?
You've got to handle comma after price:
char comma;
ss >> name >> price >> comma >> amount;
Just to clarify: the name is read with the first comma. Then the stream reads a double - finds a comma and stops here. Then you request to read an int but all it got is... a comma. You need to get rid of it to proceed.
Update:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::istringstream file("xxx, 23.0, 11\nyyy, 99.3, 100");
while (!file.eof()) {
std::string line;
std::getline(file, line);
std::istringstream line_stream(line);
std::string name;
double price;
char comma;
int amount;
line_stream >> name >> price >> comma >> amount;
std::cout << "name: " << name << std::endl;
std::cout << "price: " << price << std::endl;
std::cout << "amount: " << amount << std::endl;
std::cout << "===================" << std::endl;
}
}
Try to structure the code like this:
if( inFile.is_open() ){
string line;
while(getline(inFile, line){
...
}
}
I want to find a string in a file and replace it with user input.
Here is my rough code.
#include <iostream>
#include <fstream.h>
#include <string.h>
int main(){
istream readFile("test.txt");
string readout,
search,
replace;
while(getline(readFile,readout)){
if(readout == search){
// How do I replace `readout` with `replace`?
}
}
}
UPDATE
Here is the code that solved my problem
test.txt:
id_1
arfan
haider
id_2
saleem
haider
id_3
someone
otherone
C++ Code:
#include <iostream>
#include <fstream>
#include <string>
using namesapce std;
int main(){
istream readFile("test.txt");
string readout,
search,
firstname,
lastname;
cout << "Enter the id which you want to modify";
cin >> search;
while(getline(readFile,readout)){
if(readout == search){
/*
id remains the same
But the First name and Last name are replaced with
the user `firstname` and `lastname` input
*/
cout << "Enter new First name";
cin >> firstname;
cout << "Enter Last name";
cin >> lastname;
}
}
}
Suppose:
A user searches for id id_2. After that user enter First name and Last name Shafiq and Ahmed.
After runing this code the test.txt File must modify the record like that:
…
id_2
Shafiq
Ahmad
…
Only the id_2 record changes, the remaining file will stay the same.
This should work. I used string::find to find the desired substring within each line, and string::replace to replace it if something has been found.
Edit: I forgot about the case where the word occurs multiple times per line. Added a while to fix this.
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
ifstream in(argv[1]);
ofstream out(argv[2]);
string wordToReplace(argv[3]);
string wordToReplaceWith(argv[4]);
if (!in)
{
cerr << "Could not open " << argv[1] << "\n";
return 1;
}
if (!out)
{
cerr << "Could not open " << argv[2] << "\n";
return 1;
}
string line;
size_t len = wordToReplace.length();
while (getline(in, line))
{
while (true)
{
size_t pos = line.find(wordToReplace);
if (pos != string::npos)
line.replace(pos, len, wordToReplaceWith);
else
break;
}
out << line << '\n';
}
}
I would do what #stefaanv said:
#include <iostream>
#include <fstream.h>
#include <string.h>
int main(){
ostream outFile("replaced.txt");
istream readFile("test.txt");
string readout;
string search;
string replace;
while(getline(readFile,readout)){
if(readout == search){
outFile << replace;
}
else {
outFile << readout;
}
}
}
Edit: the above solution works if the information on each line is independent of the information on the other lines. In your update, the information on the name lines is dependent on the information on the id lines. So, to extend the above technique, you'll need to maintain state in the while loop that indicates when you've reached the end of one data block.
#include <iostream>
#include <fstream.h>
#include <string.h>
int main(){
ostream outFile("replaced.txt");
istream readFile("test.txt");
string readout;
string search, Fname, Lname;
unsigned int skipLines = 0;
cout << "Enter id which you want Modify";
cin >> search;
cout << "Enter new First name";
cin >> Fname;
cout << "Enter Last name";
cin >> Lname;
while(getline(readFile,readout)) {
if (skipLines != 0) {
skipLines--;
continue;
}
else if (readout == search) {
outFile << search << endl;
outFile << Fname << endl;
outFile << Lname << endl;
skipLines = 2;
}
else {
outFile << readout;
}
}
}
A slightly more elegant approach would be to store each data block in a struct, which allows you to use overloaded operators << & >>. This makes the code for file reading & writing more clear - it's practically the same as the code for the "data on each line is independent" situation.
#include <iostream>
#include <fstream.h>
#include <string.h>
struct NameRecord {
string id;
string fname;
string lname;
friend std::ostream& operator<<(std::ostream &os, const NameRecord &src);
friend std::istream& operator>>(std::istream &is, NameRecord &dst);
};
std::ostream& operator <<(std::ostream &os, const NameRecord &src) {
os << src.id << endl << src.fname << endl << src.lname << endl;
return os;
}
std::istream& operator >>(std::istream &is, NameRecord &dst) {
// may need to have more code to ignore whitespace, I'm not sure
if (is.good ()) {
is >> dst.id;
}
if (is.good ()) {
is >> dst.fname;
}
if (is.good ()) {
is >> dst.lname;
}
return is;
}
int main(){
ostream outFile("replaced.txt");
istream readFile("test.txt");
NameRecord inRecord, replaceRecord;
cout << "Enter id which you want Modify";
cin >> replaceRecord.id;
cout << "Enter new First name";
cin >> replaceRecord.Fname;
cout << "Enter Last name";
cin >> replaceRecord.Lname;
while (readFile.good()) {
// the >> operator reads the whole record (id, fname, lname)
readFile >> inRecord;
// the << operator writes the whole record
if (inRecord.id == replaceRecord.id) {
outFile << replaceRecord;
}
else {
outFile << inRecord;
}
}
}
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char **argv) {
if (argc < 4) {
cout << "Invalid input" << endl;
cout << "\tchange <old_word> <new_word> <file_list>";
}
fstream fs;
string tmp;
string oldw = argv[1];
string neww = argv[2];
for (int i = 3; i < argc; i++) {
fs.open(argv[i] , ios::in);
while (!fs.eof()) {
getline(fs, tmp);
while (tmp.find(oldw) != string::npos)
tmp.replace(tmp.find(oldw), sizeof(oldw), neww);
cout << tmp << endl;
}
}
fs.close();
return 0;
}
Usage:
./a.out old_word new_word filename
You probably meant to write:
tmp.replace(tmp.find(oldw), oldw.length(), neww);
for this to work properly. sizeof() will most likely always return 4.
Im trying to read a list like this one
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
and store each value into a a separate variable. The names are strings, and the other numbers are floats and an int. I can get the data from one line so far, but I dont know how to go onto the next line and do the same. Here is my code so far.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream employees;
string lastname, firstname, lastname1, firstname1, lastname2, firstname2;
float base, sales, base1, sales1, base2, sales2;
int years, years1, years2;
employees.open("employees.txt");
while (employees)
{
employees >> lastname >> firstname >> base >> sales >> years;
I want to keep it as simple as possible, I dont know user defined functions, arrays, or vectors at all yet. So is there a simple function that will just end the line at years; and go to the next line and carry on?
Thanks.
Use an array. Whenever you end up with "I want to add a number to this variable because I want more than one", if the number reaches more than 2, then you should really use an array (unless very special cases).
You may also want to use a struct to store your different values (firstname, lastname, base, sales and years) - that way, you only get a single array, rather than several different arrays.
Since this is C++, arrays means vector. In other words:
struct employee
{
string firstname, lastname;
float base, sales;
int years;
};
vector<employee> emp_table;
employee e;
while (employees >> e.firstname >> e.lastname >> e.base >> e.sales >> e.years)
{
emp_table.push_back(e);
}
Note I put the input of employees as the while-condition. This avoids an extra loop iteration and "pushing back" a second copy of the last entry when you have reached end of file.
There are many ways in C++ to accomplish what you are trying to do. One approach that allows for data validation is to use the std::getline function to read the file one line at a time and then use a std::stringstream to parse the data.. This allows you to validate the data and continue processing if the data on a line is malformed.
[As Mats noted you can use a data structure and std::vector to make storing and managing the data easier.]
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct employee
{
std::string firstname;
std::string lastname;
float base;
float sales;
int years;
};
int main()
{
std::ifstream employeeFile;
employeeFile.open("employees.txt");
std::string tmpLine;
std::vector<employee> employeeTable;
// read in an entire line at a time
while(std::getline(employeeFile, tmpLine))
{
// Place the input line into a stream that reads from
// a string instead of a file.
std::stringstream inputLine(tmpLine);
// Try parsing the data. The ! operator is used here to check
// for errors. Since we expect the data to be in a specific format
// we want to be able to handle situations where the input line
// may be malformed. For example, encountering a string where
// a number should be.
employee e;
if(!(inputLine >> e.firstname >> e.lastname >> e.base >> e.sales >> e.years))
{
// ... error parsing input. Report the error
// or handle it in some other way.
continue; // keep going!
}
// Add to the vector
employeeTable.push_back(e);
}
return 0;
}
You can use getline inside your loop to retrieve each line and then use it with a stringstream
Something like:
string line;
while(getline(employees,line))
{
//doSomething
}
If you can't use arrays to store them easily, you can put a counter to know at which line you're at, but this is very repetitive, and the number of lines in your file cannot vary:
string line;
for (int count = 1 ; count <= 3 ; count++)
{
getline(employees,line);
istringstream iss(line);
if (count == 1)
{
iss >> lastname >> firstname >> base >> sales >> years;
}
else if (count == 2)
{
iss >> lastname1 >> firstname1 >> base1 >> sales1 >> years1;
}
else if (count == 3)
{
iss >> lastname2 >> firstname2 >> base2 >> sales2 >> years2;
}
}
Opening and reading a file properly is harder than learning what an array is. If you don't use an array you have to use too many variables to hold all your data, and you have to repeatedly write the code to read from the file, rather than writing it once in a loop.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string firstNames[3];
string lastNames[3];
float heights[3];
float weights[3];
int ages[3];
ifstream infile("data.txt");
if(!infile)
{
cout << "Couldn't open file!" << endl;
return 1;
}
int count = 0;
while (infile >> firstNames[count]
>> lastNames[count]
>> heights[count]
>> weights[count]
>> ages[count] )
{
++count;
}
infile.close();
for (int i = 0; i<count; ++i) {
cout << firstNames[i] << " "
<< lastNames[i] << " "
<< heights[i] << " "
<< weights[i] << " "
<< ages[i] << " " << endl;
}
return 0;
}
--output:--
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
Compare to this disaster:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string firstName0,firstName1, firstName2;
string lastName0, lastName1, lastName2;
float height0, height1, height2;
float weight0, weight1, weight2;
int age0, age1, age2;
ifstream infile("data.txt");
if(!infile)
{
cout << "Couldn't open file!" << endl;
return 1;
}
infile >> firstName0 >> lastName0 >> height0 >> weight0 >> age0;
infile >> firstName1 >> lastName1 >> height1 >> weight1 >> age1;
infile >> firstName2 >> lastName2 >> height2 >> weight2 >> age2;
infile.close();
cout << firstName0 << " "
<< lastName0 << " "
<< height0 << " "
<< weight0 << " "
<< age0 << endl;
cout << firstName1 << " "
<< lastName1 << " "
<< height1 << " "
<< weight1 << " "
<< age1 << endl;
cout << firstName2 << " "
<< lastName2 << " "
<< height2 << " "
<< weight2 << " "
<< age2 << endl;
return 0;
}
--output:--
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
Look at all the code you have to repeat.
Note that when you use an array, the variable names become firstNames[0] (v. firstName0), lastNames[0] (v. lastName0), etc., and firstNames[1] (v. firstName1) and lastNames[1] (v. lastName0).