0

I'm trying to read data from a grid, in a 20x20 file. I'm using a two-dimensional vector of vectors of strings.

#include <iostream>
#include <string>
#include <fstream>
#include <vector>

using namespace std;

#define HEIGHT 20
#define WIDTH 20

typedef vector<vector<string> > stringGrid;

bool readGrid(stringGrid& grid, string filename) {

    grid.resize(HEIGHT);
    for (int i = 0; i < HEIGHT; i++)
        grid[i].resize(WIDTH);

    ifstream file;
    string line;

    file.open(filename.c_str());

    if (!file.is_open()) {
        return false;
    }

    for (int i = 0; i < HEIGHT; i++)
    {
        while (getline(file, line)) {
            grid[i].push_back(line);
        }
    }

    return true;
}

void displayGrid(stringGrid grid)
{

    for (int row = 0; row < HEIGHT; row++)
    {
        for (int col = 0; col < WIDTH; col++)
        {
            cout << grid[col][row];
        }
        cout << endl;
    }

}


int main(){

    stringGrid grid;

    readGrid(grid, "test.txt");

    displayGrid(grid);

    return 0;

}

However, when I run this code, the program only outputs a few blank lines. Why doesn't this code work? The logic seems sound enough.

Tetramputechture
  • 2,911
  • 2
  • 33
  • 48
  • You're pushing new elements into the outer vector which means they are getting added at the end. This will certainly cause you problems in this case. Also instead of using `HEIGHT` and `WIDTH` call vector's member function `size` instead. – Captain Obvlious May 23 '14 at 23:23
  • @CaptainObvlious can you elaborate, please? – Tetramputechture May 23 '14 at 23:27
  • @Tetramputechture, why do you need to re-size your vectors? If you call ::push_back, it will automatically adjust the size of your vector. As for the blank lines, maybe you are reading blank lines from your file too? Not sure why would you have blank lines.. – santahopar May 23 '14 at 23:33

3 Answers3

3

You can do what Kocik said or you could use vector::reserve instead of vector::resize in your code. It should then work.

reserve simply reserves enough memory to avoid reallocating memory while it's pushing back items. resize actually resizes the vector by adding n default items. In your case, those items are empty vectors of strings, so you'll get 20 of them in your vector before any other items you subsequently push back.

Here is a bit more info about the difference between the two methods.

Community
  • 1
  • 1
djikay
  • 10,450
  • 8
  • 41
  • 52
0

You use grid[i].push_back(line); after you created 20 elements with grid[i].resize(WIDTH);. Method push_back add new element on the end of the vector, so new elements will have index 21, 22 .. 40.

You have two options:

  • you can set new values to initialized elements with some iterator, or
  • you can just skip resize and push new elements to empty vector. Simply delete those two lines:
    for (int i = 0; i &lt; HEIGHT; i++)
        grid[i].resize(WIDTH);</li>
    

Kocik
  • 494
  • 2
  • 17
0

As an aside, it's generally considered bad practice to use a vector-of-vectors. Instead, use a class that wraps a single vector and does index arithmetic (either x*h+y or y*w+x depending on which major order you want).

o11c
  • 15,265
  • 4
  • 50
  • 75