Link to home
Start Free TrialLog in
Avatar of steva
steva

asked on

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
Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

Some trick:

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

    int i=20;
    TLine *p;
    p = new TLine[i];
   
   
Avatar of nagraves
nagraves

int[][] a2 = new int[20][30];
or char[][] a2 = new char[20][30];

... as it were :)
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.
That is a whole lot of unnecessary work, though it works.
     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.
Avatar of Axter
>> 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.
>>char[][] a2 = new char[20][30];

That does not even compile on a C++ compiler.
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;
};

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;
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
Avatar of steva

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of steva

ASKER

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
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.
>>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.
Avatar of steva

ASKER

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
in order to use  std::getline()  you must have "using namspace std; " at the top
Avatar of steva

ASKER

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?
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
Avatar of steva

ASKER

Thanks guys for all your help.   I went with Axter, though you all provided useful information.

Steve