简体   繁体   中英

Create 2D vector from input in C++

quick question here. I'm wondering how to create a 2D vector from user input. For a project, I am storing my "board" as a 2D vector, and the user will enter the height and width of it, as well as perhaps the starting configuration.

If my board is stored as:

vector<vector<int> > myBoard( width, vector<int> (height) ); 
//Not sure how to get width and height from input...

I will need to initialize it to the given parameters and (if the user supplies the information), fill in the board with pieces. The user will input all this information on 1 line, via 1 cin. So like this...

Please type the board config: 3 3

or

Please type the board config: 3 3 . . . . . . X . O

or

Please type the board config: 3 3 ABFDFL($%$

With the last one being an example of bad input. The first example would create a 2D vector, 3 by 3. The second would create a 2D vector, 3 by 3, and fill in the board with the position given. In this case, "." is a 0, "X" is a 1, and "O" will be a -1. That's the part I'm having the most trouble with. I could store it to a string, but it seems that going through and parsing it would be a pain in the butt...

I would try to infer the dimensions from the user input.

An example session:

A board consists of characters ., X or O.
An example board:
.XO
...
X..

Enter the board, end with two Returns:
.....
..XO.
.XXX.
OOOOO
.....

Then you would scan the first row to find the width, check each row for valid characters and the same width, and count the rows to find the height.

You could use a map where the key is a std::pair of the board coordinates read from cin as integers. The value representation could then be a int or char and is easily accessible. Then you could do things like...

if(board[std::pair(x,y)] == '.')
  //do something;

Parse it already, for heaven's sake! If all you allow is '.', 'X', and 'O', then basically all you have to do is skip whitespace. (If you love your users, you might consider allowing lower-case letters too.)

I could store it to a string, but it seems that going through and parsing it would be a pain in the butt...

Why? It's a single if / else chain or switch .

And sooner or later you'll get tired of managing vectors of vectors. I would put the whole board in a single vector and address it y * width + x . It might even become a class of its own in the future:

Piece board::getPieceAt(int x, int y) const
{
    ...
}

Pseudocode that probably leads to a square wheel.

getline( cin, board );  

find location of first space: board.find( ' ' );  
assign this to size_t height  
extract the digit(s) to a sting (or vector?): board.substr( 0, height )  
atoi this string for the height  
cut this from the string: board = board.substr( height )  
repeat for width  
initialize the realBoard vector with width and height  

if board still has chars, start filling the board  
initialize two ints for the vector coordinates  
initialize another for putting numbers onto the board  

until you get to the end of board  
send board[ i ] to a switch  
as you said, o/O = -1; x/X = 1; ./default = 0  
(unless you want bad input to interrupt execution)  
put the value into realBoard[ h ][ w ]  
add one to w;  
if it is above width, make it 0, add one to h  
if h > height, stop this function  

Here is a method using cin and its mechanisms:

#include <stdio.h>
#include <iostream>
#include <vector>
#include <limits>
#include <ctype.h>


using namespace std;


int main(){
    int x;
    int y;
    bool done = false;

    vector< int > inputs;
    char holdValue;


    while ( !done )
    {
        inputs.clear();
        cout << "Enter Data:" << endl; //something more descriptive then then this
        cin >> x >> y;
        if(cin.fail())
        {
            cin.clear();
            cin.ignore( std::numeric_limits<std::streamsize>::max(),'\n' );
            cout << "Error with your input" << endl;
            continue;
        }

        int i = 0;
        bool error = false;
        for ( ;  i < ( x * y ) && error != true ; ++i )
        {
            cin >> holdValue;
            if(cin.fail())
            {
                cin.clear();
                cin.ignore( std::numeric_limits<std::streamsize>::max(),'\n' );
                cout << "Error with your input" << endl;
                error = true;
            }
            switch( toupper( holdValue ) )
            {
                case 'X':
                    inputs.push_back( 1 );
                    break;

                case 'O':
                    inputs.push_back( -1 );
                    break;

                case '.':
                    inputs.push_back( 0 );
                    break;

                default:
                    cin.ignore( std::numeric_limits<std::streamsize>::max(),'\n' );
                    cout << "Error with your input" << endl;
                    error = true;
                    break;
            }
        }

        if( i >= ( x * y )  && error != true )
        {
            done = true;
        }
    }

    //At this piont you have a vector to do with as you please

}

But fot that amount of effort you might as well read it into a std::string and write a parser and get it over with. If will be faster and allot easier to do what you want if you get wrong input.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM