Advanced Input
NOTE: This article is part of a C++ guide, therefore only C++ code will be displayed.
There are certain programming problems that require more involved types of input. Here we discuss a couple methods to deal with such problems.
Lists of Unspecified length
Input consists of a line containing an integer representing the number of test cases. Each test case will consist of a list of integers.
Example Input:
2 2 5 10 2 8 1 2 3 4 5 6 7
getline
The first step to getting the input is to get the whole line of input to process. This can be achieved with the function getline
as shown:
#include <bits/stdc++.h>
using namespace std;
int main(){
int num_of_test_cases;
cin >> num_of_test_cases;
for(int testcase = 0; testcase < num_of_test_cases; testcase++){
string current_line;
getline(cin >> ws, current_line);
// here current_line would consist of the entire current line ex.
// "2 5 10 2 8"
// or
// "1 2 3 4 5 6 7"
}
}
Note / Tangent: cin >> ws
When using cin
and getline
simultaniously weird behavior can occur. When cin
is used it leaves the "\n"
character at the end, so the getline
would contain the character "\n"
instead of the nextline. To avoid this we can use cin >> ws
as ws
will remove any remaining whitespace(spaces, tabs, newlines,etc.), allowing getline
to work correctly. If a program used only getline
instead you could use getline(cin, string);
to get from input into that string.
stringstreams
Since we have the list of numbers on a string now, it would be nice to use similar functionality to cin
to get the input.
Luckily we can achieve this with stringstreams. Stringstreams basically transform a normal string into a stream like cin
, from which we can use the <<
and >>
operators:
#include <bits/stdc++.h>
using namespace std;
int main(){
int num_of_test_cases;
cin >> num_of_test_cases;
for(int testcase = 0; testcase < num_of_test_cases; testcase++){
string current_line;
getline(cin >> ws, current_line);
stringstream ss(current_line);
// here we can do ss >> num to input the current integer into num
int first_num;
cin >> first_num; // 2 on the first test case, 1 on the second test case
}
}
However, we still dont know the number of elements, so we don't know the number of times we have to use ss >> num;
. To get the numbers we can use a while loop that will run as long as there are numbers to read in.
Final Example
#include <bits/stdc++.h>
using namespace std;
int main(){
int num_of_test_cases;
cin >> num_of_test_cases;
for(int testcase = 0; testcase < num_of_test_cases; testcase++){
string current_line;
getline(cin >> ws, current_line);
stringstream ss(current_line);
vector<int> numbers;
int current_number;
while(ss >> current_number){
numbers.push_back(current_number);
}
// here the numbers vector should have all the numbers!
// ...
}
}
Keep in mind this works with any other standard use of cin (i.e. with floats/doubles, space separated strings, etc.)
getting comma separated numbers
While it might sound more complicated to get such numbers, we can actually use the same approach as before! The only difference is we need to get rid of the ","
character after every time we read in a number. This can be done with some stringstream functions, like so:
#include <bits/stdc++.h>
using namespace std;
int main(){
int num_of_test_cases;
cin >> num_of_test_cases;
for(int testcase = 0; testcase < num_of_test_cases; testcase++){
string current_line;
getline(cin >> ws, current_line);
stringstream ss(current_line);
vector<int> numbers;
int current_number;
while(ss >> current_number){
numbers.push_back(current_number);
// here we check if the next character is a comma, and if it is, we ignore it
if (ss.peek() == ','){
ss.ignore();
}
}
// here the numbers vector should have all the numbers!
// ...
}
}