Pass a 2D vector to a function

Well, I decided to try and write a simple spreadsheet, so created a single cell first as a struct.
1
2
3
4
5
6
struct Cell
{
	string text;
	int number;
        // Will add in more..  float, double etc.
};


Then created a vector..
1
2
3
4
const int Spreadsheet_Width = 53;
const int Spreadsheet_Height = 76;

struct Cell Spreadsheet[Spreadsheet_Height][Spreadsheet_Width];


I would like to be able to send the vector to a function, so I can initialize the contents of it, but, I can't figure out a way to do it.

Tried Init( Spreadsheet); in main, with the function created as..
void Init(vector <Cell>& Spreadsheet[int Spreadsheet_Height][int Spreadsheet_Width]) but I get red squiggles under some of the wording. I have written programs that send plain vectors with no problem, but a 2D one is stumping me. Could someone point me in the correct direction on getting this to work? If you need the whole program, I can upload it to dropbox where it can be DL'd. Right now, it's 10,418 bytes and growing. Thanks for any help.
This is an ordinary 2-D array:
 
    Cell Spreadsheet[Spreadsheet_Height][Spreadsheet_Width];


The equivalent declaration for a 2-D vector would look like this:
 
    vector<vector<Cell>> Spreadsheet(Spreadsheet_Height, vector<Cell>(Spreadsheet_Width));


Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <vector>

using namespace std;

struct Cell
{
    string text;
    int number;
        // Will add in more..  float, double etc.
};

void print (const vector<vector<Cell>>& Spreadsheet)
{
    for (const auto & row : Spreadsheet)
    {
        for (const auto & cell : row)
        {
            cout << cell.number << ' ';
        }
        cout << '\n';
    }

}

void init(vector<vector<Cell>>& Spreadsheet)
{
    for (size_t i=0; i<Spreadsheet.size(); i++)
    {
        for (size_t j=0; j<Spreadsheet[i].size()  ; j++)
        {
            Spreadsheet[i][j].number = 7;
        }
    }

}

int main()
{
    const int Spreadsheet_Width  = 53;
    const int Spreadsheet_Height = 76;
    
    vector<vector<Cell>> Spreadsheet(Spreadsheet_Height, vector<Cell>(Spreadsheet_Width));  
        
    init(Spreadsheet);  
    print(Spreadsheet);     
}


I would like to be able to send the vector to a function, so I can initialize the contents of it

You might add a constructor to the struct Cell, for example to set the numbers to zero. The string is by default initialised as an empty string.
@Chervil

Thanks, that was a big help. I was now able to initialize the full spreadsheet, but I'm having a small problem trying to figure out how to print only a section of it. On the console, I need to print out only the first 19 columns, and the first 18 rows. Then using the arrow keys, I can shift the columns left or right and the rows, up or down. So, if the console is showing columns 0 to 19, and I want to press the right arrow, I now need to show column 0, then columns 2 to 20. Pressing right again will display column 0, then columns 3 to 21. Of course, the same applies to the up/down display, as well. It shows rows 0 to 18, then pressing down, shows row 0 and rows 2 to 19, etc.
The reason for always showing row 0 and column 0, is because they are initialized with 'A' to 'AZ' for row 0, and 1 to 75 for column 0, and I want those always displayed.

I'm not sure how I can stop the entire spreadsheet vector from being displayed.

On the console, I need to print out only the first 19 columns, and the first 18 rows.


I'm sure there are many ways to do something like that.
This is part of some code I was playing around with.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const int Spreadsheet_Width  = 53;
const int Spreadsheet_Height = 76;

const int Height = 5;
const int Width  = 7;

struct Rectangle {
    
    int top;
    int left;
    int bottom;
    int right;
    
    Rectangle() : top(0), left(0), bottom(Height), right(Width) { }
    
    void move_left()
    { 
        if (left > 0)  {  left--;  right = left + Width;   }
    }
    
    void move_right()
    { 
        if (left+Width < Spreadsheet_Width)  {  left++;  right = left + Width;   }
    }

    void move_up()
    { 
        if (top > 0)  {  top--;  bottom = top + Height;   }
    }
    
    void move_down()
    { 
        if (top+Height < Spreadsheet_Height)  {  top++;  bottom = top + Height;   }
    }
    
    
};




void print_window(const vector<vector<Cell>>& Spreadsheet, const Rectangle& rect)
{
    for (int i=rect.top; i<rect.bottom; i++)
    {
        for (int j=rect.left; j<rect.right; j++)
        {
            cout << setw(4) << Spreadsheet[i][j].number;
        }
        cout << '\n';
    }
}


Elsewhere in the code I declare a Rectangle object and use the keyboard to trigger the calling of the member functions such as rect.move_right(); and then call the print function, print_window(Spreadsheet, rect); along with a few other bits and pieces to position the cursor on the console and so on.


Hope those fragments are of some use, the complete code was a bit of a mess, so it seemed unnecessary to post it.
@Chervil
The last bit of code you showed me looks nice, but I'm just learning about this 2d vector stuff. I'm not sure how to declare the Rectangle object, nor call the member functions. When I tried plugging in the Rectangle struct and print_window function, I get the red squiggle line under Rectangle in the print_window function.
Anyway, I'm having problems with getting it to compile before trying to add the new coding into it.
I'm getting a couple of errors when I try to initialize the Spreadsheet vector
1
2
Error 2 error LNK2019: unresolved external symbol "void __cdecl Init_Spreadsheet(class std::vector<class std::vector<struct Cell,class std::allocator<struct Cell> >,class std::allocator<class std::vector<struct Cell,class std::allocator<struct Cell> > > > &)" (?Init_Spreadsheet@@$$FYAXAAV?$vector@V?$vector@UCell@@V?$allocator@UCell@@@std@@@std@@V?$allocator@V?$vector@UCell@@V?$allocator@UCell@@@std@@@std@@@2@@std@@@Z) referenced in function "int __cdecl main(void)" (?main@@$$HYAHXZ)	C:\Users\staff\Documents\Visual Studio 2012\Projects\Spreadsheet\Spreadsheet\Spreadsheet.obj	Spreadsheet
Error 1 error LNK2028: unresolved token (0A0004CF) "void __cdecl Init_Spreadsheet(class std::vector<class std::vector<struct Cell,class std::allocator<struct Cell> >,class std::allocator<class std::vector<struct Cell,class std::allocator<struct Cell> > > > &)" (?Init_Spreadsheet@@$$FYAXAAV?$vector@V?$vector@UCell@@V?$allocator@UCell@@@std@@@std@@V?$allocator@V?$vector@UCell@@V?$allocator@UCell@@@std@@@std@@@2@@std@@@Z) referenced in function "int __cdecl main(void)" (?main@@$$HYAHXZ)	C:\Users\staff\Documents\Visual Studio 2012\Projects\Spreadsheet\Spreadsheet\Spreadsheet.obj	Spreadsheet


My function looks like..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void init_Spreadsheet(vector<vector<Cell>>& Spreadsheet)
{
	for (size_t i=0; i<Spreadsheet.size(); i++)// Spreadsheet_Height
	{
		
		for (size_t j=0; j<Spreadsheet[i].size(); j++) // Spreadsheet_Width
		{
			if( i == 0 && (j>0 && j<27))
			{
				Spreadsheet[i][0].number = i; // Assign 0 to 75 to start of each
				Spreadsheet[0][j].text = 'A'+ (j-1);// Spreadsheet[0][1] to Spreadsheet[0][26] eqauals 'A' to 'Z'
			}
			if( i == 0 && j > 26)
			{
				Spreadsheet[0][j].text = "A";
				Spreadsheet[0][j].text += 'A'+(j-27);// Spreadsheet[0][27] to Spreadsheet[0][53] eqauals 'AA' to 'AZ'
			}
			else
				Spreadsheet[i][j].number = 7;
		}
	}
	Spreadsheet[0][0].text = "";
}
]
Those are linker errors.

I notice the code has the function named
 
init_Spreadsheet
but the error messages refer to
 
Init_Spreadsheet
One has an upper-case 'I', the other a lower-case 'i'.
@Chervil

Thanks. I totally missed that. I kept looking inside the function and trying to figure what I did wrong there. Now it compiles and displays correctly on screen. I'll call this completed and start another thread if or when, I run into more problems.
I'm not sure how to declare the Rectangle object, nor call the member functions. When I tried plugging in the Rectangle struct and print_window function, I get the red squiggle line under Rectangle in the print_window function.

I tried to tidy up my code a bit so I could post it here, and ran into some problem with the Rectangle struct. I didn't look too deeply int the details, but there was a name clash with something in the windows.h header. To fix that, I added a namespace. Since this is nothing special, I just called it xyz.

The below code may or may not compile on your system, it uses some non-standard stuff, and some windows functionality.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <sstream>
#include <conio.h>
#include <Windows.h>

void gotoxy( int column, int line )
{
    COORD coord;
    coord.X = column;
    coord.Y = line;
    SetConsoleCursorPosition(
        GetStdHandle( STD_OUTPUT_HANDLE ),
        coord
    );
}

const int Spreadsheet_Width  = 53;
const int Spreadsheet_Height = 76;

const int Left  = 331;
const int Right = 333;
const int Up    = 328;
const int Down  = 336;

const int Height = 20;
const int Width  = 12;


namespace xyz {

struct Rectangle {
    
    int top;
    int left;
    int bottom;
    int right;
    
    Rectangle() : top(0), left(0), bottom(Height), right(Width) { }
    
    void move_left()
    { 
        if (left > 0)  {  left--;  right = left + Width;   }
    }
    
    void move_right()
    { 
        if (left+Width < Spreadsheet_Width)  {  left++;  right = left + Width;   }
    }

    void move_up()
    { 
        if (top > 0)  {  top--;  bottom = top + Height;   }
    }
    
    void move_down()
    { 
        if (top+Height < Spreadsheet_Height)  {  top++;  bottom = top + Height;   }
    }
    
    
};

} // --- end namespace xyz ---

struct Cell
{
    std::string text;
    int number;
        // Will add in more..  float, double etc.
};

std::string base26(unsigned int n)
{
    const char * alphabet = "ZABCDEFGHIJKLMNOPQRSTUVWXYZ";
    std::string result;
    
    result = alphabet[n % 26 + 1];
    n /= 26;
    
    while (n)   
    {
        result = alphabet[n % 26 ] + result;
        n--;
        n /= 26;
    }
    
    return result;
    
}

void print (const std::vector<std::vector<Cell>>& Spreadsheet)
{
    std::ostringstream oss;
    for (const auto & row : Spreadsheet)
    {
        for (const auto & cell : row)
        {
            oss.clear(); oss.str("");
            oss << cell.text << cell.number;
            std::cout << std::setw(4) << oss.str();
            
        }
        std::cout << '\n';
    }

}


void init(std::vector<std::vector<Cell>>& Spreadsheet)
{
    for (size_t i=0; i<Spreadsheet.size(); i++)
    {
        for (size_t j=0; j<Spreadsheet[i].size()  ; j++)
        {
            Spreadsheet[i][j].number = i+1;
            Spreadsheet[i][j].text   = base26(j);
        }
    }

}


void print_window(const std::vector<std::vector<Cell>>& Spreadsheet, const xyz::Rectangle& rect)
{
    std::ostringstream oss;

    for (int i=rect.top; i<rect.bottom; i++)
    {
        for (int j=rect.left; j<rect.right; j++)
        {
            oss.clear(); oss.str("");
            const Cell & c = Spreadsheet[i][j];

            oss << c.text << c.number;
            std::cout << std::setw(6) << oss.str();

        }
        std::cout << '\n';        
    }

}

int getkey()
{
    int ch = getch();
    if (ch == 0 || ch == 0xE0)
    {
        ch = getch();
        return 256 + ch;
    }
    return ch;
}

int main()
{    
    std::vector<std::vector<Cell>> Spreadsheet(Spreadsheet_Height, std::vector<Cell>(Spreadsheet_Width));  
        
    init(Spreadsheet);  
//  print(Spreadsheet);     
    

    xyz::Rectangle rect;

    gotoxy(0,0);
    print_window(Spreadsheet, rect);


    // Press ESCAPE key to exit
    int key = 0;
    while ((key = getkey() ) != 27)
    {
        if      (key == Left)  rect.move_left();  // cout << "left\n";
        else if (key == Right) rect.move_right(); // cout << "right\n";
        else if (key == Up)    rect.move_up();    // << "up\n";
        else if (key == Down)  rect.move_down();  // << "down\n";
//        else std::cout << key << '\n';
        gotoxy(0,0);
        print_window(Spreadsheet, rect);

    } 
         
}


@Chervil

That works like a charm, and looks good too.

If you would like to see what my program is looking like so far, I'll put it in dropbox.

dropbox Spreadsheet code
https://www.dropbox.com/s/gt1hi5aiql7as9w/Spreadsheet.cpp?dl=0

It uses a function called Grid that I wrote to display the spreadsheet cells, color, and of course, a gotoXY function

Next, I have to write functions to allow filling and updating, the cells. I've got high confidence I'll be able to.

Thanks you SO MUCH for your help. You went far above simple suggestions and nudges. Really appreciate it.

I do program only for fun and learning. And I've learned quite a bit from you.
Last edited on
@Whitenite1
Thanks, you're welcome. Actually, I've learned stuff from you too. I think the gotoxy() function originally came from one of your posts, and a number of other things too. I learn from everyone actually. Just trying to think of answers to some of the questions on this forum is a learning process in itself.

Nowadays I'm programming only for fun or things which interest me. It just happened that something about your project caught my attention so I got a bit caught up in it. I didn't intend my code to be quite so long, but I wanted it to be something which worked, shown in context.

Thanks for the dropbox link, I'll take a look.
@Chervil

Thank you. Oh, by the way, I haven't written instructions yet on the spreadsheet program use. All it can do right now, is add a 'XX' to a cell. To specify which cell, you first press '@' symbol, then a small or capital 'A' or up to an 'AZ' then the row 1 to 75. Press 'Enter'. A 'XX' is then placed in the corresponding cell. Use the cursor keys to shift the cells in the desired directions. The column letter and row numbers, always stay on screen.

Topic archived. No new replies allowed.