I need to parse a C++ stdin input which looks something like this:
N M (pairs)
0 0
2 1 (0,1)
2 0
5 8 (0,1) (1,3) (2,3) (0,2) (0,1) (2,3) (2,4) (2,4)
If N > 0 && M > 0, then M pairs will follow. It is a single line input so I have no idea how to do it.
I have some solution, but something tells me it’s not the best one.
void input(){
int a[100][2];
int n,m;
char ch;
cin >> n >> m;
for ( int i = 0; i < m; i++) {
cin >> ch >> a[i][0]>> ch>> a[i][1]>>ch;
}
cout << n << " " << m << " \n";
for ( int i=0; i < m; i++ ) {
cout << "(" << a[i][0] << " ," << a[i][1] << ")";
}
}
My question is what is the best / more correct way to do this?
Since input data to applications never can be trusted there is an importance of adding error checks to see that the data provided is indeed valid (otherwise the result of the application might suffer from errors while parsing).
The “C++ way” of handling errors such as this is to throw an exception when a problem arise in the functions responsible for parsing data.
The caller of this function will then wrap the call in a try-catch-block to catch errors that might appear.
With a user-defined-type..
Defining your own type for holding your pairs of data will greatly improve the readability of your code, the output from the below implementation and the one found later in this post is the same.
The one thing I’ve noticed that might be hard for programmers to grasp about the above is the use of
s >> std::ws; it’s used to consume available white-spaces so that we can use.peekto get the next non-whitespace character available.The reason I implemented a static function
read_frominstead ofostream& operator>>(ostream&, Pair&)is that the later will require that we create an object before even reading from the stream, which in some cases are undesirable.Normally I wouldn’t recommend naming non-const variables in only uppercase, but to make it more clear which variable contains what I use the same name as your description of the input.
Without the use of user-defined-types
The straight forward method of parsing the data as well as having checks for errors is to use something as the following, though it could be greatly improved by using User Defined Objects and operator overloads.
If the stringstream isn’t empty after step 4 or iss.good () returns false anywhere inbetween the steps the is a syntax error in the data read.
Sample implementation
The source can be found by following the link below (code put elsewhere to save space):