tags:

views:

100

answers:

1

I'm trying to work with vectors of vectors of ints for a sudoku puzzle solver I'm writing.

Question 1:

If I'm going to access a my 2d vector by index, do I have to initialize it with the appropriate size first?

For example:

typedef vector<vector<int> > array2d_t;

void readAPuzzle(array2d_t grid)
{
    for(int i = 0; i < 9; i++)
        for(int j = 0; j < 9; j++)
            cin >> grid[i][j];
    return;
}

int main()
{
    array2d_t grid;
    readAPuzzle(grid);
}

Will seg fault. I assume this is because it is trying to access elments of grid that have not yet been initialized?

I've swapped out grid's declaration line with:

array2d_t grid(9, vector<int>(9, 0));

And this seems to get rid of this seg fault. Is this the right way to handle it?

Question 2:

Why is it that when I try to read into my grid from cin, and then print out the grid, the grid is blank?

I'm using the following code to do so:

void printGrid(array2d_t grid)
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            cout << grid[i][j] + " ";
        }
        cout << endl;
    }
}

void readAPuzzle(array2d_t grid)
{
    for(int i = 0; i < 9; i++)
        for(int j = 0; j < 9; j++)
            cin >> grid[i][j];

    return;
}

int main()
{
    array2d_t grid(9, vector<int>(9, 0));
    printGrid(grid);
    readAPuzzle(grid);
    printGrid(grid);
}

And I attempt to run my program like:

./a.out < sudoku-test

Where sudoku-test is a file containing the following:

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

The first call to printGrid() gives a blank grid, when instead I should be seeing a 9x9 grid of 0's since that is how I initialized it. The second call should contain the grid above. However, both times it is blank.

Can anyone shed some light on this?

+5  A: 

Q1: Yes, that is the correct way to handle it. However, notice that nested vectors are a rather inefficient way to implement a 2D array. One vector and calculating indices by x + y * width is usually a better option.

Q2A: Calculating grid[i][j] + " " does not concatenate two strings (because the left hand side is int, not a string) but instead adds the numeric value to a pointer (the memory address of the first character of the string " "). Use cout << grid[i][j] << " " instead.

Q2B: You are passing the array by value (it gets copied) for readAPuzzle. The the function reads into its local copy, which gets destroyed when the function returns. Pass by reference instead (this avoids making a copy and uses the original instead):

void readAPuzzle(array2d_t& grid)
Tronic
@Tronic, ah I see. I thought the default behavior for vectors would be to pass by reference, like arrays do.
Salaban
This doesn't explain why the first printGrid() doesn't give me a 9x9 grid of 0's though? If it is copied, the zero's should still be present when printing.
Salaban
Arrays are a strange special case. I wouldn't say that arrays are passed by reference, but rather that when you write [], you actually get a pointer (that is then passed by value). It is a matter of perspective, though.
Tronic
Replace `cout << grid[i][j] + " ";` with `cout << grid[i][j] << " ";`
Nikolai N Fetissov
@Nikolai: Excellent catch.
Greg Hewgill
Added Q2A, which answers to the first half of Q2. String concatenation by + only works when at least one of the sides is std::string, and the other is either C string or another std::string.
Tronic
Thank you everyone!
Salaban
Btw, does anyone else find it a shameful that STL doesn't provide any 2D containers? Such things would be highly useful.
Tronic