Reputation: 13
Is there a reason why this would happen? I have the same exact file saved under two different names. One is test.csv, the other is text.txt. The content is identical. When I open text.txt using an ifstream object, my code runs as expected and parses the data into an object. When I open test.csv, no data is ever collected by my ifstream object and the code malfunctions. Is there any sort of extra step that needs to be taken when opening a .csv as opposed to a .txt?
Here is the code that actually does the input:
Team::Team(ifstream& fin)
{
string temp;
stringstream convert;
//Get team #
getline(fin, temp, ',');
idNumber = stringToInt(temp);
//Get team letter
getline(fin, temp, ',');
idLetter = temp[0];
//Get team name
getline(fin, name, ',');
//Get team type
getline(fin, type, ',');
//Get team rating
getline(fin, temp, ',');
rating = stringToDouble(temp);
//Get team notes
getline(fin, notes, ',');
//Get toss info
getline(fin, temp, ',');
canToss = stringToBool(temp);
getline(fin, tossType, ',');
//Get female info
getline(fin, temp, ',');
hasFemales = stringToBool(temp);
getline(fin, temp, ',');
femaleNumber = stringToInt(temp);
getline(fin, temp, ',');
femaleRating = stringToDouble(temp);
//Get Auto info
getline(fin, temp, ',');
hasAuto = stringToBool(temp);
getline(fin, autoType, ',');
getline(fin, temp, ',');
autoScore = stringToInt(temp);
//Get Drive Info
getline(fin, temp, ',');
driveMotors = stringToInt(temp);
getline(fin, temp, ',');
driveRatio = stringToDouble(temp);
getline(fin, driveType, ',');
//Get hang info
getline(fin, temp, ',');
canHang = stringToBool(temp);
getline(fin, hangType, ',');
//Get stash info
getline(fin, temp, ',');
canStash = stringToBool(temp);
//Get lift indo
getline(fin, temp, ',');
liftMotors = stringToInt(temp);
getline(fin, temp, ',');
liftRatio = stringToDouble(temp);
getline(fin, liftType, ',');
//Get competition info
getline(fin, temp, ',');
driverSkills = stringToInt(temp);
getline(fin, temp, ',');
programmingSkills = stringToInt(temp);
getline(fin, temp, ',');
ranking = stringToInt(temp);
getline(fin, temp, ',');
wins = stringToInt(temp);
getline(fin, temp, ',');
ties = stringToInt(temp);
getline(fin, temp, ',');
losses = stringToInt(temp);
getline(fin, temp);
SPs = stringToInt(temp);
}
Upvotes: 0
Views: 253
Reputation: 185970
If none of the read operations are fetching anything, it's most likely that you didn't successfully open the file, while there could be numerous reasons for this, the first step is to detect this. Do you test that the file opens successfully? You can do something like this:
if (ifstream fin("test.csv")) {
Team team(fin);
⋮
} else {
std::cerr << "Failed to open test.csv\n";
}
While I'm at it, may I suggest a code restructure? About 80% of coding is maintenance, so clarity and speed of visual processing should be a key consideration in your coding style:
getline(fin, temp , ','); idNumber = stringToInt (temp);
getline(fin, temp , ','); idLetter = temp[0];
getline(fin, name , ',');
getline(fin, type , ',');
getline(fin, temp , ','); rating = stringToDouble(temp);
getline(fin, notes , ',');
getline(fin, temp , ','); canToss = stringToBool (temp);
getline(fin, tossType , ',');
getline(fin, temp , ','); hasFemales = stringToBool (temp);
getline(fin, temp , ','); femaleNumber = stringToInt (temp);
getline(fin, temp , ','); femaleRating = stringToDouble(temp);
getline(fin, temp , ','); hasAuto = stringToBool (temp);
getline(fin, autoType , ',');
getline(fin, temp , ','); autoScore = stringToInt (temp);
//Get Drive Info
getline(fin, temp , ','); driveMotors = stringToInt (temp);
getline(fin, temp , ','); driveRatio = stringToDouble(temp);
getline(fin, driveType, ',');
//Get hang info
getline(fin, temp , ','); canHang = stringToBool (temp);
getline(fin, hangType , ',');
//Get stash info
getline(fin, temp , ','); canStash = stringToBool (temp);
//Get lift indo
getline(fin, temp , ','); liftMotors = stringToInt (temp);
getline(fin, temp , ','); liftRatio = stringToDouble(temp);
getline(fin, liftType , ',');
//Get competition info
getline(fin, temp , ','); driverSkills = stringToInt (temp);
getline(fin, temp , ','); programmingSkills = stringToInt (temp);
getline(fin, temp , ','); ranking = stringToInt (temp);
getline(fin, temp , ','); wins = stringToInt (temp);
getline(fin, temp , ','); ties = stringToInt (temp);
getline(fin, temp , ','); losses = stringToInt (temp);
As an additional improvement, you could further refactor your code to avoid so many read operations:
Team::Team(ifstream& fin)
{
string temp;
getline(fin, temp);
const char * ctemp = temp.c_str();
std::vector<char> buf(ctemp, ctemp + temp.count() + 1);
char * lasts, * s = buf.data();
auto next = [&]{
char * result = strtok_r(s, ",", &lasts);
assert(result); // …or throw
s = NULL;
return result;
};
idNumber = stringToInt (next());
idLetter = next()[0];
name = next();
type = next();
rating = stringToDouble(next());
⋮
programmingSkills = stringToInt (next());
⋮
}
As a final step, you might even want to use a convenient extractor class:
class CsvLine {
public:
CsvLine(const std::string & line) {
const char * temp = line.c_str();
buf_.assign(temp, temp + line.length() + 1));
s_ = buf_.data();
}
CsvLine & operator>>(string & x) { x = next() ; return *this; }
CsvLine & operator>>(char & x) { x = *next() ; return *this; }
CsvLine & operator>>(int & x) { x = stringToInt (next()); return *this; }
CsvLine & operator>>(bool & x) { x = stringToBool (next()); return *this; }
CsvLine & operator>>(double & x) { x = stringToDouble(next()); return *this; }
private:
std::vector<char> buf_;
char * s_, * lasts_;
char * next() {
char * result = strtok_r(s_, ",", &lasts_);
assert(result); // …or throw
s_ = NULL;
return result;
};
};
Team::Team(ifstream& fin)
{
string line;
getline(fin, line);
CsvLine(line)
>> idNumber >> idLetter >> name >> type >> rating >> notes
>> canToss >> tossType
⋮
>> driverSkills >> programmingSkills >> ranking >> wins >> ties >> losses;
}
Upvotes: 1