Assigning 2-dimensional array with new

Anyone know how to assign memory for a two-dimensional array of characters with new?  I've tried:

   int i=20;
    char ** p;
    p = new char [i][30];

Thanks,
Steve
stevaAsked:
Who is Participating?
 
AxterConnect With a Mentor Commented:
>> As you requested, the intention of the two-dimensional array is to hold an array of lines.  

For this requirement, it would be safer if you use a vector of std::string.

std::vector<std::string> MyArray;

std::string LineStr;

while(std::getline(myfstream, LineStr))
{
   MyArray.push_back(LineStr);
}

By using the above container, you don't have to worry about the value of "i", and you don't have to worry about a 250 bound limit.

Otherwise, you would have to run through the file, to determine the quantity of lines, and then create your dynamic array.
Then run through the file again, to actually fetch the data.
That would be very inefficient, and not as safe is the vector container.
0
 
Jaime OlivaresSoftware ArchitectCommented:
Some trick:

typedef struct {
  char line[30];
} TLine;

    int i=20;
    TLine *p;
    p = new TLine[i];
   
   
0
 
nagravesCommented:
int[][] a2 = new int[20][30];
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
nagravesCommented:
or char[][] a2 = new char[20][30];

... as it were :)
0
 
bcsonkaCommented:
Hi,

Here's another way to allocate a two-dimensional array of characters:

============================================================================

// Allocate array of character pointers
char **array2D = new char* [20];

// For each character pointer, allocate an array of characters
for(int i = 0; i < 20; i++)
{
      array2D[i] = new char[30];
}

//
// Utilitze array2D
//

// For each character pointer allocated above, delete its array of characters
for(int j = 0; j < 20; j++)
{
      delete [] array2D[j];
}

// Finally, delete the array of character pointers
delete [] array2D;

============================================================================

I hope that helps.
0
 
nagravesCommented:
That is a whole lot of unnecessary work, though it works.
0
 
efnCommented:
     int i=20;
      char (*p)[30];
      p = new char [i][30];

The second line declares p as a pointer to an array of 30 chars.  The parentheses are required--without them, it declares p as an array of 30 pointers.
0
 
AxterCommented:
>> That is a whole lot of unnecessary work, though it works.

I'ts not unnecessary work.

The code you posted, will not give you the desired results for a two dimensional array.
0
 
AxterCommented:
>>char[][] a2 = new char[20][30];

That does not even compile on a C++ compiler.
0
 
AxterCommented:
I recommend using a 2DArray class or vector<vector<> > type class.

It's much safer then using pointers.

Here's a simple 2DArray class

template < class T, int ROW_T = 0, int COL_T = 0 >
class dynamic_2d_array
{
public:
    dynamic_2d_array(int row, int col):m_row(row),m_col(col), m_data((row!=0&&col!=0)?new T[row*col]:NULL){}
    dynamic_2d_array():m_row(ROW_T),m_col(COL_T), m_data(new T[ROW_T*COL_T])
      {if (!COL_T || !ROW_T) {int x[ROW_T] = {{ROW_T}};int y[COL_T] = {{x[0]}};}}
    ~dynamic_2d_array(){if(m_data) delete []m_data;}
    inline T* operator[](int i) {return (m_data + (m_col*i));}
    inline T const*const operator[](int i) const {return (m_data + (m_col*i));}
private:
    const int m_row;
    const int m_col;
    T* m_data;
};

0
 
AxterCommented:
Example usuage:

      dynamic_2d_array < int > dyn_2dArray(Q_Col, Q_Row);
            for(int i0 = 0; i0 < Q_Col; ++i0) {
                  for(int i1 = 0; i1 < Q_Row; ++i1) {
                        dyn_2dArray[i0][i1] = random_value();
                        cout << dyn_2dArray[i0][i1]  << endl;
0
 
Jaime OlivaresSoftware ArchitectCommented:
steva,
Please explain us your intention to use the bidimensional array.
If just need to have an array of "strings", then my example could be helpful and simple.
If you need a true bidimensional array, then you will need to create a specialized C++ class.

I will retouch my example a bit:
typedef struct {
  char col[30];
} TLine;

    int i=20;
    TLine *p;
    p = new TLine[i];

You can use it as:

p[10].col[15] = 'A';  // single char assignment

or

strcpy(p[10].col, "test");  // entire string assignment
0
 
stevaAuthor Commented:
As you requested, the intention of the two-dimensional array is to hold an array of lines.  The diminsions will be [i][250], where I'm allowing 250 characters per line and "i" is determined after I've done getline() to EOF, i.e., I know how many lines are in the file. I  will then  read  the lines of the file into the array, edit the individual lines (without extending any line beyond its 250 allotted chars) and write the array back out to the file.

Steve
0
 
stevaAuthor Commented:
Axter,

Your vector of LineStrs has an elegant feel, but I'm afraid it will force me to learn a lot more C++ than I intended for this small project.  How do I find out more about the characteristics of an std::string, for example? Why do we need to bring in std::?  How is std::getline() different from the iostream getline()?  I couldn't find anything in the VC++ documentation about std::stuff.  Your code compiles under VC++ 6.0, but generates warnings about reverse interators being truncated to 255 characters. What are these about?

Steve
0
 
nagravesCommented:
std::getline() makes sure that you're using the getline in the std namespace. (when you use: using namespace std;) 'using namespace std' is the namespace which the entire Standard c++ library is declared.. sdt::getline uses strings, iostream::getline doesn't afaik.
0
 
AxterCommented:
>>reverse interators being truncated to 255 characters. What are these about?

That's a bug in the compiler, which you can ignore.
You can remove the warnings by adding the following line to the top of your code:

#pragma warning(disable: 4786)

>>How do I find out more about the characteristics of an std::string, for example?
If you're using VC++, then just use the compiler's help file.
Double clikc on string in your code, and then press F1
You can also check out the MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcstdlib/html/vclrfcpluspluslibraryoverview.asp

Both string and vector are listed in above site.  Click on the object you want info on, and then you can click on the [member] link listed at the bottom left corner of the web page.

Both string and vector's are pretty simple containers that can save you a lot of time coding.
0
 
stevaAuthor Commented:
nagraves,

>>std::getline() makes sure that you're using the getline in the std namespace. (when you use: using namespace >>std;) 'using namespace std' is the namespace which the entire Standard c++ library is declared.

So if I put 'using namespace std;' at the top of my program, can I just code 'getline()' without the std::?

Steve
0
 
nagravesCommented:
in order to use  std::getline()  you must have "using namspace std; " at the top
0
 
stevaAuthor Commented:
Yes, but if I put 'using namespace std;' at the top is it then understood that getline() is the std version so I don't need to write std::getline() everytime?
0
 
efnCommented:
Yes, if you put "using namespace std;" at the top, you don't need to prefix "getline" with "std::"--unless you have something else called "getline" in scope.

If you would prefer to avoid all this standard library stuff, you can just use the declaration I posted above.  The only disadvantages are that you have to read the file twice and you have to make sure the lines are no longer than 249 characters, as Axter pointed out.  If you can live with those disadvantages, you don't have to grapple with the standard library or namespaces.

--efn
0
 
stevaAuthor Commented:
Thanks guys for all your help.   I went with Axter, though you all provided useful information.

Steve
0
All Courses

From novice to tech pro — start learning today.