Search code examples
c++consoleuser-input

C++ How to handle user input given in contests/problems format


Recently I have been starting to participate in c++ contests but I cannot find the best way to handle user input when given in this format.

E.g. 4 and 3 are the dimensions of the next block of input

4 3 
1 2 4 5
1 6 7 4 
1 5 0 0

The problem I've been having is that sometimes the automatic testing machine successfully can test its inputs and sometimes no, so far the method I've been using is the next

std::vector<std::vector<char>> vec;
void get_lines(std::string in) {
    std::vector<char> line(in.begin(), in.end());
    vec.push_back(line);
}

std::cin >> height >> width;//this is in main()
std::cin.ignore();
for (int i = 0; i < height; i++)
{
    std::getline(std::cin, input);
    get_lines(input);
    input = "";
}

But I'm sure it's not the most efficient nor the more stable way to handle this type of input.

How can I handle user input in the above-mentioned format so that the testing machine can easily input its values?


Solution

  • First of all, I am sorry for you that you made the decision to participate in such contests. It will help you to learn on how to solve algorithms, but they usually use an extremely bad programming style.

    Anyway. Back to your question. As always. It depends. If you have data that are just separated by white space, you can use nearly always formatted input functions with the extractor operator ´>>´. This operator will ignore (skip) all white space in standard mode, including the "new line" at the end of a line. So, no need to read line by line.

    The good point ofthis "contest pages" is that input is always be considered correct. So, you do not need to do input-error checking or data plausibilisation. The will always use some test environment, where they "push" the data in your code via input redirection. In real life, user input is always very error prone and must be checked carefully.

    And you see that, although not necessary, they give the dimensions of the matrix, to ease up data input (this would normally not be necessary, because we can find out by ourselves).

    • So, first read the dimensions.
    • With that, construct your ´std::vector´
    • Then use 2 nested range based for loops to read the values

    One of many possible examples could look like this:

    #include <iostream>
    #include <vector>
    
    int main() {
    
        // Define variables that will hold the dimension of the matrix
        size_t numberOfRows{}, numberOfColumns{};
    
        // Get user input, the dimension of the matrix
        std::cin >> numberOfRows >> numberOfColumns;
    
        // Define our container, including its size
        std::vector<std::vector<int>> matrix(numberOfRows, std::vector<int>(numberOfColumns, 0));
        
        // Read values from user input
        for (std::vector<int>& row : matrix) for (int& i : row)
            std::cin >> i;
        
        // Show output
        for (const std::vector<int>& row : matrix) {
            for (const int& i : row) std::cout << i << ' ';
            std::cout << '\n';
        }
    }
    

    Also the use of std::istream_iterators in conjunction with range constructors can be used here. But, as said. It depends.

    If they have Comma Separated Values, or white space within values, like strings, then you need to use other mechanisms.