Is it possible to 'throw away' read value from input stream? - c++

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;

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

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;

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);
}

Related

How to do is >> std::skipws >> through multiple indices of an array?

Let's say you have std::array<int, SIZE> a, and you have saved each element of a into a file in one line separated by a space. Then you want to read them with a std:istream& is via:
is >> std::skipws >> a[0] >> a[1] >> a[2] >> ... >> a[SIZE-1];
How to write this generically for any value of SIZE. Even though there are other easy ways of doing this, I'm curious how it is done with this particular method.
How to write this generically for any value of SIZE.
There are control structures for repeating an operation a variable number of times: loops.
For example:
is >> std::skipws;
for(auto& el : a) {
is >> el;
}

C++: how to input values separated by comma(,)

int a, b, c, d;
There are 4 variables.
I want user to input 4 values, and each value is separated by comma(,)
Just like this:
stdin:
1,2,3,4
The following code works in C
scanf("%d,%d,%d,%d", &a, &b, &c, &d);
But how should I code in C++?
I’m kind of surprised at the incorrect commentary here[1].
There are two basic routes you can take:
handle the separator with a manipulator-style object, or
imbue the stream with a specialized facet that requires whitespace to include a comma.
I will focus on the first; it is typically a bad idea to imbue shared streams with weird behaviors even temporarily (“shared” in the sense that other parts of your code have access to it as well; a local stringstream would be an ideal candidate for imbuing with specialized behaviors).
A ‘next item must be a comma’ extractor:
#include <cctype>
#include <iostream>
struct extract
{
char c;
extract( char c ): c(c) { }
};
std::istream& operator >> ( std::istream& ins, extract e )
{
// Skip leading whitespace IFF user is not asking to extract a whitespace character
if (!std::isspace( e.c )) ins >> std::ws;
// Attempt to get the specific character
if (ins.peek() == e.c) ins.get();
// Failure works as always
else ins.setstate( std::ios::failbit );
return ins;
}
int main()
{
int a, b;
std::cin >> a >> extract(',') >> b;
if (std::cin)
std::cout << a << ',' << b << "\n";
else
std::cout << "quiznak.\n";
}
Running this code, the extract manipulator/extractor/whatever will succeed only if the next non-whitespace item is a comma. It fails otherwise.
You can easily modify this to make the comma optional:
std::istream& operator >> ( std::istream& ins, optional_extract e )
{
// Skip leading whitespace IFF user is not asking to extract a whitespace character
if (!std::isspace( e.c )) ins >> std::ws;
// Attempt to get the specific character
if (ins.peek() == e.c) ins.get();
// There is no failure!
return ins;
}
...
std::cin >> a >> optional_extract(',') >> b;
Etc.
[1] cin >> a >> b; is not equivalent to scanf( "%d,%d", ...);. C++ does not magically ignore commas. Just as in C, you must treat them explicitly.
The same for the answer using getline() and a stringstream; while the combination is valid, the actual problem is just shifted from std::cin to another stream object, and still must be treated.

Read at once inputs string and integer separated by a space in c++

I was wondering if, like in C, in C++ there was a way to take at once two different type of varibales as inputs.
For example I am supposed to read a command (a string) followed by an index(an integer) from a user, and they separated by a space.
The >> operator for a std::istream is overloaded for many different types. Any class which inherits >> from std::istream can read inputs from all the types >> is overloaded for. This means you can use the >> operator with std::cin, std::ifstream, std::istringstream, etc. to read in multiple types.
The basic syntax for your case would have the form
std::string s;
int n;
std::cin >> s >> n; // or std::ifstream, etc.
Of course you should perform error checking to make sure you actually received what you expected. You can use the ! operator to check if the stream is (not) in a good state. So in your case you might use the following:
std::string s;
int n;
if (!std::cin) {
// error handling here
} else {
std::cin >> s; // get the std::string
}
if (!std::cin) {
// error handling here
} else {
std::cin >> n; // get the int
}

ignore to the n° whitespace with ifstream

I have a data file with a lot of columns of doubles but I want to read only two of them with a while loop
double x, y;
ifstream in;
double foo;
while( in >> foo ) {
in >> foo;
in >> foo;
...
in >> x;
in >> y;
... something with x and y
}
Two questions
1) There is a way to do the same thing without a fake double foo?
2) there is a way to do that without repeat in >> foo (or a for loop) like stream to the n° whitespace with a one-line code? There is a built-in function to skip to the n° whitespace?
What I would suggest instead is to read an entire row in a string and use a stringstream to manipulate it or just use something like find_last_of functions from the string class itself to pick out the last two columns and then convert it back to a double.

fstream with a string delimiter or two char

I have this situation where I need to get two int values from each row inside a file with this format:
43=>113
344=>22
Is it possible to do someting like setting a delimiter equal to => and than use >> operator to assign ints?
ifstream iFile("input.in");
int a,b;
iFile >> a >> b;
Also can be done autoamtically to output with similar format?
oFile << a << b;
instead of
oFile << a << "=>" << b;
Thanks.
You can't do it directly, without any extra code when reading or
writing, but you can write a manipulator which handles it for
you more explicitly:
std::istream&
mysep( std::istream& source )
{
source >> std::ws; // Skip whitespace.
if ( source.get() != '=' || source.get() != '>' ) {
// We didn't find the separator, so it's an error
source.setstate( std::ios_base::failbit );
}
return source;
}
Then, if you write:
ifile >> a >> mysep >> b;
, you will get an error is the separator is absent.
On output, you can use a similar manipulator:
std::ostream&
mysep( std::ostream& dest )
{
dest << "=>";
return dest;
}
This has the advantage of keeping the information as to what the
separator is isolated in these two specific functions (which
would be defined next to one another, in the same source file),
rather than spread out where ever you are reading or writing.
Also, these data presumably represent some particular type of
information in your code. If so, you should probably define it
as a class, and then defined operators >> and << over that
class.
Given a and b are variables of inbuilt types, you can not define your own user-defined operators for streaming them (the Standard library already provides such functions).
You could just write out code with the behaviour you want...
int a, b;
char eq, gt;
// this is probably good enough, though it would accept e.g. "29 = > 37" too.
// disable whitespace skipping with <iomanip>'s std::noskipws if you care....
if (iFile >> a >> eq >> gt >> b && eq == '=' && gt == '>')
...
OR wrap a and b into a class or struct, and provider user-defined operators for that. There are plenty of SO questions with answers explaining how to write such streaming functions.
OR write a support function...
#include <iomanip>
std::istream& skip_eq_gt(std::istream& is)
{
char eq, gt;
// save current state of skipws...
bool skipping = is.flags() & std::ios_base::skipws;
// putting noskipws between eq and gt means whatever the skipws state
// has been will still be honoured while seeking the first character - 'eq'
is >> eq >> std::noskipws >> gt;
// restore the earlier skipws setting...
if (skipping)
is.flags(is.flags() | std::ios_base::skipws);
// earlier ">>" operations may have set fail and/or eof, but check extra reasons to do so
if (eq != '=' || gt != '>')
is.setstate(std::ios_base::failbit)
return is;
}
...then use it like this...
if (std::cin >> a >> skip_eq_gt >> b)
...use a and b...
This function "works" because streams are designed to accept "io manipulator" functions that reconfigure some aspect of the stream (for example, std::noskipws), but for a function to be called it just has to match the prototype for an (input) io manipulator: std::istream& (std::istream&).
If you have always have => as the deliminator, you can write a function that will parse lines of the document.
void Parse(ifstream& i)
{
string l;
while(getline(i,l))
{
//First part
string first = l.substr(0, l.find("=>"));
//Second part
string second = l.substr(l.find("=>")+2, l.length());
//Do whatever you want to do with them.
}
}