Reputation: 41
I'm currently trying to load a text file into struct data members. Each number is separated by a comma.
#include<string>
#include<sstream>
using namespace std;
struct server{
bool isBusy;
};
struct pass{
double arrivalTime = 0;
double serviceTime = 0;
int classType = 0;
};
int main(){
string fileName;
string line;
pass Pass;
cout << "Enter file name: ";
cin >> fileName;
ifstream fin(fileName);
while (getline(fin, line, ','))
{
/*NEED HELP HERE*/
fin >> Pass[0].arrivalTime;
fin >> Pass[0].serviceTime;
fin >> Pass[0].classType;
}
}
Here is an example of the text file.
0.951412936,2.131445423,0
1.902743503,2.010703852,0
2.537819984,2.326199911,0
3.425838997,1.603712153,0
3.502553324,0.998192867,0
3.917348666,1.49223429,0
4.391605986,0.831661367,0
4.947059678,0.8557003,0
5.429305232,2.42029408,0
The data in the text file follows this format:
arrivalTime,serviceTime,classType
As you can see i have split the line up and stored it in "line" using the comma delimiter, but i am unsure how to load each number into the struct in the while loop.
Any help would be appreciated.
Upvotes: 1
Views: 9315
Reputation: 375
#include<string>
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
struct server{
bool isBusy;
};
struct pass{
double arrivalTime;
double serviceTime;
int classType;
friend std::istream & operator >>(std::istream &in, pass &p) {
char c;
in >> p.arrivalTime >> c >> p.serviceTime >> c >> p.classType;
return in;
}
};
int main(){
string fileName;
string line;
cout << "Enter file name: ";
cin >> fileName;
ifstream fin(fileName.c_str(), ifstream::in);
vector<pass> passes;
pass Pass;
while (fin>>Pass)
passes.push_back(Pass);
for(vector<pass>::const_iterator iter = passes.begin();
iter != passes.end();
++iter)
std::cout<<iter->arrivalTime<<" "<<iter->serviceTime<<" "
<<iter->classType<<std::endl;
}
Upvotes: 1
Reputation: 171263
This loop is wrong:
while (getline(fin, line, ','))
{
/*NEED HELP HERE*/
fin >> Pass[0].arrivalTime;
fin >> Pass[0].serviceTime;
fin >> Pass[0].classType;
}
You are reading everything from the stream up to the next ','
character, then trying to read more from the stream.
Given the input file:
0.951412936,2.131445423,0
1.902743503,2.010703852,0
2.537819984,2.326199911,0
Your program reads "0.951412936"
into line
(and discards the ','
) then tries to read the next input into Pass[0].arrivalTime
but the next input is 2.131445423, which was meant to be the serviceTime (which you already read into line
).
As Shreevardhan suggests you can define an operator for reading your struct from a stream. I would make it more reliable like so:
struct ExpectedChar { char expected; };
// read a character from a stream and check it has the expected value
std::istream& operator>>(std::istream& in, const ExpectedChar& e)
{
char c;
if (in >> c)
if (c != e.expected) // failed to read expected character
in.setstate(std::ios::failbit);
return in;
}
// read a struct pass from a stream
std::istream& operator>>(std::istream& in, pass& p)
{
ExpectedChar comma{ ',' };
in >> p.arrivalTime >> comma >> p.serviceTime >> comma >> p.classType;
return in;
}
This will stop reading if the input file does not meet the expected format. Now you can do:
while (fin >> Pass)
{
// do something with each pass
}
if (!fin.eof()) // stopped reading before end-of-file
throw std::runtime_error("Invalid data in input file");
This will keep reading a pass
from the file until reading fails, either because it reached the end of the file, or because there was some bad data in the file. If there is bad data it throws an exception.
Upvotes: 1
Reputation: 249
while (getline(fin, line))
{
sscanf(line.c_str(), "%lf,%lf,%d", &arrivalTime, &serviceTime, &classType);
}
Upvotes: 1
Reputation: 12641
Define an istream operator >>
for your struct. Something like
struct pass {
double arrivalTime = 0;
double serviceTime = 0;
int classType = 0;
friend std::istream & operator >>(std::istream & in, pass & p) {
char c;
in >> p.arrivalTime >> c >> p.serviceTime >> c >> p.classType;
return in;
}
};
Then, simply
pass Pass;
fin >> Pass;
Upvotes: 2
Reputation: 395
Here is hint;
string line;
string temp;
string::size_type sz;
while (getline(cin, line))
{
istringstream ss( line );
getline( ss, temp, ',' );
double arrivalTime = stod(temp, &sz);
getline( ss, temp, ',' );
double serviceTime = stod(temp, &sz);
getline( ss, temp, ',' );
double classType = stod(temp, &sz);
cout << arrivalTime << ' '
<< serviceTime << ' '
<< classType << endl;
}
Upvotes: 0