3

I process some data with data in columns like,

1 -0.004002415458937208 0.0035676328502415523
2 -0.004002415796209478 0.0035676331876702957
....

I am only interested in the last two values. I usually find it convenient to read the values as:

std::ifstream file(file_name);
double a, b;
for (lines) {
    //      | throwing away the first value by reading it to `a`
    file >> a >> a >> b;
    store(a, b);
}

I'm not sure how readable this is for others, and it might be thought of as an error when the structure of the data is not known. Could I somehow make it look more explicit that I really want to throw away the first read value?

I wanted something in the line of this, but nothing worked:

file >> double() >> a >> b; // I hoped I could create some r-value kind of thing and discard the data in there
file >> NULL >> a >> b;
pingul
  • 3,351
  • 3
  • 25
  • 43
  • 3
    `_` is a valid identifier and I've seen it get used for variables with unused contents before. Other names: `discarded`, `ignored`, `consumed`, `unused`, `destroyer_of_hope` (well, okay, not that last one) – jaggedSpire Dec 08 '16 at 17:22
  • I name a variable called eater and that eats the unneeded input. – NathanOliver Dec 08 '16 at 17:23
  • I was thinking that creating a variable for it would be redundant, and not using it afterwards would create a warning (which I realise it does not). This might be a decent workaround. – pingul Dec 08 '16 at 17:27
  • Why you say " from std::cin " if you read from file? – Rama Dec 08 '16 at 17:28
  • @Rama Valid point. My thinking was that as the operator has the same functionality as for `std::cin` it would make more direct sense to people passing by. – pingul Dec 08 '16 at 17:30
  • 3
    `file >> junk >>...` would work. That what I do to discard input. – Topological Sort Dec 08 '16 at 17:34
  • I don't understand. You have to read the characters in order to skip the field. The costly operation of reading needs to take place. Whether you use the data or not is your decision. So, just read the field and don't process the data. – Thomas Matthews Dec 08 '16 at 18:48
  • @ThomasMatthews Yes, I am aware. I am not concerned about performance but readability, and I was looking for suggestions to make my intention clearer. – pingul Dec 09 '16 at 11:44

3 Answers3

10

If you don't want to create a variable explicitly to be ignored, and you feel explicitly ignoring the value with calls to manipulate the stream are too verbose, you could take advantage of the operator>> overload for std::istream that takes a std::istream&(*)(std::istream&) function pointer:

template <typename CharT>
std::basic_istream<CharT>& ignore(std::basic_istream<CharT>& in){
    std::string ignoredValue;
    return in >> ignoredValue;
}

to be used like:

std::cin >> ignore >> a >> b;

and if you wanted to verify that it was of a form that could be read into a type you could supply an additional template argument specifying the type of ignored value:

// default arguments to allow use of ignore without explicit type
template <typename T = std::string, typename CharT = char>
std::basic_istream<CharT>& ignore(std::basic_istream<CharT>& in){
    T ignoredValue;
    return in >> ignoredValue;
}

to be used like:

std::cin >> ignore >> a >> b;
// and
std::cin >> ignore<int> >> a >> b;

demo on coliru

jaggedSpire
  • 4,423
  • 2
  • 26
  • 52
9

You can use std::istream::ignore.

E.g.:

file.ignore(std::numeric_limits<std::streamsize>::max(), ' '); //columns are separated with space so passing it as the delimiter.
file >> a >> b;
Dim_ov
  • 1,421
  • 9
  • 14
  • Good answer. I feel it's a little verbose however, and that it defeats the purpose of the short `file >> a >> a >> b;`. – pingul Dec 08 '16 at 17:32
  • @pingul well, you can create a custom stream manipulator to make the syntax a bit prettier. Take a look at this answer. It should be easy to adopt it to your needs: http://stackoverflow.com/a/29414164/2355119 – Dim_ov Dec 08 '16 at 17:37
1

You can use file::ignore(255, ' ') to ignore characters until the next space.

std::ifstream file(file_name);
double a, b;
for (lines) {
    //  skip first value until space
    file.ignore(255, ' ');
    file >> a >> b;
    store(a, b);
}

or you can use an auxiliary variable to store the first value:

std::ifstream file(file_name);
double aux, a, b;
for (lines) {
    //  skip first value
    file >> aux >> a >> b;
    store(a, b);
}
  • 5
    `file.ignore()` should use `std::numeric_limits::max()` to ignore all characters until the next space. Using `255` artificially limits you to a max of 255 ignored characters. – Karl Nicoll Dec 08 '16 at 17:40
  • I think it isn't a problem because the first data is an integer number. The problem can be if the line starts with 1 or more spaces. In this case, the code doesn't work as need!! – Jesus R. Leal Dec 08 '16 at 17:57