Its hard to do this directly. This is because you need to use a combination of formatted(operator>>
) and non-formatted(std::getline
) input routines.
You want to use operator>>
to read the id
field (and correctly parse an integer); but then you also want to use the function std::getline()
, using the third parameter '\t'
, to read a tab delimited field (Note: The field terminator defaults to '\n'
line delimited values).
Normally you don't want to use mix the usage of operator>>
and std::getline()
together because of how they handle white space.
So the best solution is to write your own input operator and handle that extra space explicitly in a controlled manner.
How to do it:
I would create a class to represent the line.
struct Line
{
int id;
std::string col;
std::string uid;
void swap(Line& other) noexcept {
using std::swap;
swap(id, other.id);
swap(col, other.col);
swap(uid, other.uid);
}
friend std::istream& operator>>(std::istream& in, Line& data);
};
Then you need to define in an input operator for reading the line.
std::istream& operator>>(std::istream& in, Line& data)
{
Line tmp;
if (// 1 Read the id. Then disicard leading white space before second field.
(linestream >> tmp.id >> std::ws) &&
// 2 Read the second field (which is terminated by tab)
(std::getline(tmp.col, linestream, '\t') &&
// 3 Read the third field (which is terminated by newline)
(std::getline(tmp.uid, linestream)
// I am being lazy on 3 you may want to be more specific.
)
{
// We have correctly read all the data we need from
// the line so set the data object from the tmp value.
data.swap(tmp);
}
return in;
}
Now it can be used easily.
Line line;
while (infile >> line) {
### operations on row, col and uid ####
}