Input Handling Examples
2D grid with no spaces between cells (marioyc)
I used to read grids with the second method below but this one is much simpler! I had to save it here for future references, borrowed from marioyc. In this specific example (469Wetlands of Florida), we are not given the dimensions of grid (ugh).
1 LLLLLLLLL LLWWLLWLL LWWLLLLLL |
int tests, n, m;
scanf("%d\n", &tests);
std::vector<std::string> grid;
std::string line;
while (tests--) {
grid.clear();
// found this pretty sweet way of reading the grid (much better than my original)
// in marioyc's github
while (1) {
std::getline(std::cin, line);
if (line[0] != 'W' && line[0] != 'L') {
break; // not grid data anymore
}
grid.push_back(line);
}
m = (int) grid.size(); // number of rows
n = (int) grid[0].size(); // number of columns
}
Or if you know the dimensions,
int tests, n, m;
scanf("%d\n", &tests);
while (tests--) {
scanf("%d %d\n", &m, &n);
std::vector<std::string> grid;
std::string line;
for (int i = 0; i < m; i++) {
std::getline(std::cin, line);
grid.push_back(line);
}
}
2D grid with no spaces between cells
This is done using std::getline like above, but here we save the grid as a 2D char array instead of multiple vectors of strings (above). In this particular, we know the dimensions but not the total number of tests.
3 111 222 333 2 444 333 |
char m[MAX][MAX];
bool read_input() {
int n;
scanf("%d\n", &n);
std::string line;
for (int i = 0; i < n; i++) {
std::getline(std::cin, line); // a line here is 123
if (line.size() == 0) { return false; } // done reading
for (int j = 0; j < n; j++) {
m[i][j] = line[j];
}
}
return true;
}
Unbounded tests and variable length strings (use sstream)
We have a bunch of tests but we don’t know the number of tests. This is an example:
5 E 0.01 *A ... 10 S 2.23 Q* A 9.76 CKM ... |
Each test case starts with the number of lines in the test case. Each line contains three values and so we use std::istringstream to extract the values. The following works although not pretty.
#include<sstream>
// for each test case, we read the number of lines in the test case
int n;
scanf("%d\n", &n);
std::string line, value, neighbors;
char planet;
for (int i = 0; i < n; i++) {
std::getline(std::cin, line);
// this is my hack to know we're done and there are no more lines
if (line.size() == 0) { return; }
// take this line now and process it the way you want
// in this specific case, we know we have three values
std::istringstream iss(line);
iss >> planet >> value >> neighbors;
}
2D grid with ints and characters
This is a square grid with 5 rows and 5 columns. Also, we’re only given the lower triangle only in the matrix since this is an unweighted graph. The main issue was that an ‘x’ was used to indicate that there is no edge between the vertices.
5 50 10 x x 20 40 40 x 30 60 |
int d;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
if (scanf("%d", &d) == 1) {
distance[i][j] = distance[j][i] = d;
} else {
scanf("%*c"); // read x
}
}
}
3D grid with no space between cells
This is from problem “532 - Dungeon Master”. Here we know when to terminate. We also know the number of rows, colums and the height (number of levels). There is also an extra new line between each board.
2 4 5 SXXXX X@@@X X@@XX @@@X@ @@@@@ @@@@@ @@X@@ @@XXX 1 3 3 S@@ @E@ @@@ 0 0 0 |
char m[MAX][MAX][MAX];
int L, R, C, start_k, start_i, start_j;
scanf("%d %d %d\n", &L, &R, &C);
if (L == 0 && R == 0 && C == 0) { break; }
char line[MAX];
// each level
for (int k = 0; k < L; k++) {
// each board
for (int i = 0; i < R; i++) {
fgets(line, MAX, stdin); // a line here is @@XX@
for (int j = 0; j < C; j++) {
m[k][i][j] = line[j]; // put each char in its cell
if (m[k][i][j] == 'S') { // record the start position
start_k = k;
start_i = i;
start_j = j;
}
}
}
fgets(line, MAX, stdin); // get the nasty extra line between levels
}
Strings with variable number of ints
Consider a number of lines where each line consists of a variable number of ints. We can use std::istringstream and use a while loop to read as many ints as possible from that line.
#include<sstream>
int n;
scanf("%d\n", &n);
std::string line;
for (int i = 0; i < n; i++) {
std::getline(std::cin, line);
std::istringstream iss(line);
int num;
while (iss >> num) {
// do something with num
}
}