Allocate 2d array of strings

Hello if i have 2d array of strings, how can i allocate first field ?
and i need from this
1
2
const int width = 5;
string array[25][width];

make this
1
2
3
4
const int width = 5;
int rows;
cin >> rows;
string array[rows][width];

but i must allocate is somehow but how ? :)
Dynamically sizing array is ugly business.

You'd need do something like:

1
2
3
4
std::string **array = new std::string*[width];

for( int i=0; i < width; ++i )
   array[i] = new std::string[rows];


It's all sort of messy, especially considering you're going to have to loop through and deallocate the memory when you're done.

In all truth, you're best bet is to use std::vector. You can easily have vector of vector of strings too:
std::vector<std::vector<std::string>> str_vecs;

EDIT: I had a spare couple of minutes at work. Here's a quick 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
#include <iostream>
#include <string>
#include <vector>

int main( int argc, char* argv[] )
{
    std::vector<std::vector<std::string>> str_vec;

    // You can get these values from std::cin
    // I'm hard-coding for simplicity
    int row = 5;
    int width = 25;

    // Vectors, by their nature, can resize dynamically
    // However, we can also preset desired sizes
    str_vec.resize( row );

    for( auto &i : str_vec )
        i.resize( width );

    // You can assign and access just like a regular 2D array
    str_vec[0][0] = "This is a string!";
    std::cout << str_vec[0][0] << std::endl;

    // You can get current size by using size()
    std::cout << "Current size of row vector: " << str_vec.size() << std::endl;
    std::cout << "Current size of width vector: " << str_vec[0].size() << std::endl;

    return 0;
}
Last edited on
I know vectors will be far away better solution for this....unfortunately we are not allowed use vectors yet :(
when i try this, program crash.

1
2
3
4
5
6
7
8
   
     int row = 25;
    const int width = 5;
    string **array = new string*[width];
    for( int i=0; i < width; ++i )
        {
        array[i] = new string[row];
        }


but works with this
1
2
const int width = 5;
string array[25][width];

I dont know what im doing wrong.
It's working fine for me.

Complete solution:
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
#include <iostream>
#include <string>

int main( int argc, char* argv[] )
{
    int row = 25;
    int width = 5;

    std::string **arr = new std::string*[width];

    for( int i = 0; i < width; ++i )
        arr[i] = new std::string[row];

    for( int i = 0; i < width; ++i )
    {
        for( int j = 0; j < row; ++j )
        {
            arr[i][j] = "Blank string";
        }
    }

    // Pick one to print
    std::cout << arr[3][10] << std::endl;

    // Clean Up
    for( int i=0; i < width; ++i )
        delete [] arr[i];

    delete [] arr;

    return 0;
}


What do you mean by crashing?
Last edited on
Crashing like "program stop working" "Process terminated with status -1073741510 (0 minutes, 12 seconds)", it crasching when i want put some information into strings. clines1(); scan file from which i read and put in numberlines number of rows.

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
const int width = 5;
    clines1();
    int row = numberlines;


    string array[25][width];
/*
    string **array = new string*[width];
    for( int i=0; i < width; ++i )
        {
        array[i] = new string[row];
        }

 */

    int rows = 0;

    ifstream number1(file_out1.c_str(), fstream::out);
    if (number1.is_open())
    {
        string line, word;

        while (getline(number1, line))
        {
            istringstream ss(line);
            int cols = 0;
            while (getline(ss, word, ',') )
            {
                array[rows][cols] = word;
                cols++;
            }
            rows++;
        }
    }
    number1.close();
Last edited on
If I had to take a guess I'd say the code inside of your loops is trying to access an out of bounds array subscript.

I'd check to make sure that rows and cols are always within the confines of your array sizes.

For example, I can crash my program with the following line:

arr[5][20] = "Break me!";
Last edited on
true i think it will be problem somewhere there but idk where, also idk why it work with string array[25][width]; and dont work with allocating ? when it allocate it to same number :/
@iHutch105: Your examples are column-major. C/C++ is row-major. Nefri's attempt mixed the indices. On a square matrix one would not notice the error.

On the other hand there is reading from input too without checking whether (malformed) input adds too many words per line and too many lines.

std::ifstream opened with fstream::out flag?


The static array is a continuous block of memory. The dereference operation(s) on array does "pointer math" in order to retrieve desired element.

One can use dynamic 2D array with only 2 'new []' and 2 'delete []'. One reserves a block of rows*cols for the data, and the second reserves rows pointers to the beginning of each row within the block. On iHutch105's model there are multiple separate small blocks, rather than one for the data.

One could possibly use a std::string (*arr)[5]; instead of the array of pointers to data block(s), reducing the need to one 'new []' and one 'delete []'.
Cheers, Keskiverto. In hindsight, I should have probably gone with row/col, rather than row width, as I would have been less inclined to mix up the order that way. In fact, I'm not even sure why I didn't. I think I may have been blindly copying.
Last edited on
So, how it should looks like in my code ? We do not learn pointers yet so im kinda lost with this.
> if i have 2d array of strings, how can i allocate first field ?
> make this
1
2
3
4
> const int width = 5;
> int rows;
> cin >> rows;
> string array[rows][width];

> but i must allocate is somehow but how ? :)

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 <memory>

int main()
{
    const int COLS = 5 ;
    using row_type = std::string[COLS] ;

    std::size_t rows ;
    std::cout << "rows? " ;
    std::cin >> rows ;

    {
        row_type* array = new row_type[rows] ;

        // use array
        for( std::size_t i = 0 ; i < rows ; ++i )
            for( std::size_t j = 0 ; j < COLS ; ++j )
                array[i][j] = "hello" ;

        for( std::size_t i = 0 ; i < rows ; ++i )
        {
            for( std::size_t j = 0 ; j < COLS ; ++j )
                std::cout << array[i][j] << ' ' ;
            std::cout << '\n' ;
        }

        delete[] array ;
    }

    // better (exception safe etc.)
    {
        std::unique_ptr< row_type[] > array( new row_type[rows] ) ;

        // use array
        for( std::size_t i = 0 ; i < rows ; ++i )
            for( std::size_t j = 0 ; j < COLS ; ++j )
                array[i][j] = "bonjour" ;

        for( std::size_t i = 0 ; i < rows ; ++i )
        {
            for( std::size_t j = 0 ; j < COLS ; ++j )
                std::cout << array[i][j] << ' ' ;
            std::cout << '\n' ;
        }
    }
}

http://ideone.com/OOV59N
To JLBorges:
I trying use your code but, Codeblock same as Visual studio cant compile your file, i have around 20 errors there... Probebly it dont take 8 line using row_type = std::string[COLS] ;
Yes, C++98 will choke on the type alias. Replace the type alias on line 8 with a typedef

1
2
// using row_type = std::string[COLS] ;
typedef std::string row_type[COLS] ;


And there was no std::unique_ptr<>. Remove it.

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
#include <iostream>
#include <string>
#include <memory>
 
int main()
{
    const int COLS = 5 ;
    // using row_type = std::string[COLS] ; // ***
    typedef std::string row_type[COLS] ; // ***
 
    std::size_t rows ;
    std::cout << "rows? " ;
    std::cin >> rows ;
 
    {
        row_type* array = new row_type[rows] ;
 
        // use array
        for( std::size_t i = 0 ; i < rows ; ++i )
            for( std::size_t j = 0 ; j < COLS ; ++j )
                array[i][j] = "hello" ;
 
        for( std::size_t i = 0 ; i < rows ; ++i )
        {
            for( std::size_t j = 0 ; j < COLS ; ++j )
                std::cout << array[i][j] << ' ' ;
            std::cout << '\n' ;
        }
 
        delete[] array ;
    }
}

http://ideone.com/FSdc8A
thank you :)
Topic archived. No new replies allowed.