2D arrays question

C

csx

Hi everyone!

two quick questions relating to arrays.

Q1,
Is it possible to re-assign array elements?

int array[2][2] = {{2,4}, {4,5}};

array[1][1] = {2,3}

just causes compiler errors! Do I have to assign at the beginning?



Q2,
My other 'main' question relates to 2-Dimensional arrays.

I need to create the size of my 2D array at run time. I have a couple of
functions that provide the dimensions I need. I need to call the function
like:

two_dimensional_array(maxRows, numLeafs)

but then, assign the values after, hence my first question. Can values be
asigned after?

Here is the code I currently have? Is this a good implementation? Any
suggestions would be much appreciated.



int ** myArray = 0; // in C++ 0==NULL

void two_dimensional_array(int rows, int cols)
{
int Rows, Cols;
if (myArray != NULL) {
for (int i = 0; i < Rows; i++) {
myArray = new int[Cols];
}
}
}

int _tmain(int argc, _TCHAR* argv[])
{
myArray = new *int[Rows];
return 0;
}
 
M

Mike Wahler

csx said:
Hi everyone!

two quick questions relating to arrays.

Q1,
Is it possible to re-assign array elements?

Yes, individually.
int array[2][2] = {{2,4}, {4,5}};

array[1][1] = {2,3}

Invalid syntax.

Also, array[1][1] denotes a single type 'int' object.
How do you expect to store two values in a single object?

Guessing at which elements you really want to change:

array[1][0] = 2;
array[1][1] = 3;
just causes compiler errors! Do I have to assign at the beginning?

You must assign each element's value individually.
If your values form an appropriate 'pattern' this
can often be done in a loop.
Q2,
My other 'main' question relates to 2-Dimensional arrays.

I need to create the size of my 2D array at run time. I have a couple of
functions that provide the dimensions I need. I need to call the function
like:

two_dimensional_array(maxRows, numLeafs)

but then, assign the values after, hence my first question. Can values be
asigned after?
Yes.

Here is the code I currently have? Is this a good implementation? Any
suggestions would be much appreciated.



int ** myArray = 0; // in C++ 0==NULL

This is not an array, it's a pointer. It does
not point to any storage you can use.
You must allocate some memory and assign its
address to the pointer. I see you tried to
below, but fall short.

void two_dimensional_array(int rows, int cols)

That's not a very desriptive name. I'd call it
e.g. 'load2darray', 'populate2darray' or something like that.
Also note that you never call this function in the code
you've posted.
{
int Rows, Cols;

Array dimensions should be stored in type 'size_t'
Type 'int' won't necessarily be able to represent
all possible array index values. 'size_t' is
guaranteed to be able to.

if (myArray != NULL) {
for (int i = 0; i < Rows; i++) {
myArray = new int[Cols];
}
}
}

int _tmain(int argc, _TCHAR* argv[])


int main(int argc, char *argv[]) {

No "Windows-isms" allowed here.
myArray = new *int[Rows];

Invalid syntax.

myArray = new int*[Rows];

But this only allocates storage for 'Rows' pointers.
There's still no storage for them to point to.
return 0;
}

The difficulty so many have with arrays is one reason
for the invention of standard library containers such
as std::vector.

I recommend you use containers instead of arrays in
C++ programs, unless there's a compelling reaons to
do otherwise (e.g. interface with C or existing,
nonmodifiable code).

std::vector<std::vector> > arr2d;

-Can do anything an array can do, and more.
-Does all the memory management for you.
-Is 'flexible' -- will grow or shrink its size as needed.
-Carries its size with it, no need to pass an extra 'size'
to functions as with arrays.

If you insist upon using arrays, perhaps you'll find
useful an example in C I posted to comp.lang.c today. Look
for my name as author of a post in a thread entitled
"Re: How to free allocated memory?"

It uses the C functions 'malloc()' and 'free()' for
memory management, but you should be able to drop in
new[] and delete[] in their place -- you *must* do this
if you're creating arrays of types which have ctors/dtors,
or they won't get called.

But if you don't have to, don't use arrays. Use containers.
Really.

HTH,
-Mike
 
K

Kevin Goodsell

csx said:
Hi everyone!

two quick questions relating to arrays.

Q1,
Is it possible to re-assign array elements?

Of course, unless the elements are 'const'.
int array[2][2] = {{2,4}, {4,5}};

array[1][1] = {2,3}

just causes compiler errors! Do I have to assign at the beginning?

Of course it's an error. The {...} syntax is only for initializers. Why
are you trying to give one element two values anyway?

array[1][1] = 3;
Q2,
My other 'main' question relates to 2-Dimensional arrays.

I need to create the size of my 2D array at run time.

Say no more.

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.19
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15

The short answer is: Use std::vector.
I have a couple of
functions that provide the dimensions I need. I need to call the function
like:

two_dimensional_array(maxRows, numLeafs)

but then, assign the values after, hence my first question. Can values be
asigned after?

Here is the code I currently have? Is this a good implementation? Any
suggestions would be much appreciated.



int ** myArray = 0; // in C++ 0==NULL

Evil global variable.
void two_dimensional_array(int rows, int cols)
{
int Rows, Cols;
if (myArray != NULL) {
for (int i = 0; i < Rows; i++) {
myArray = new int[Cols];
}
}
}


Why wouldn't you have this function return the pointer rather than
acting on an evil global variable?

Besides that, it seems really broken. Why doesn't it allocate the
initial int* array? Why does it indiscriminately overwrite the elements
of the array that myArray points to? What if those pointers already
pointed to dynamic memory?
int _tmain(int argc, _TCHAR* argv[])

_tmain is a reserved identifier in the global namespace (as are all
identifiers beginning with an underscore followed by a lower-case
letter). That means you may not use it as a name in the global
namespace. Also, _TCHAR is reserved in all contexts (as are all
identifiers beginning with an underscore followed by an upper-case
letter or another underscore), and you may not use it at all. In
general, avoid identifier names beginning with an underscore. (And try
posting *standard* C++ code when you post here.)
{
myArray = new *int[Rows];
return 0;

Uh, memory leak? What exactly was this supposed to demonstrate?

-Kevin
 
K

Kevin Goodsell

Mike said:
The difficulty so many have with arrays is one reason
for the invention of standard library containers such
as std::vector.

I recommend you use containers instead of arrays in
C++ programs, unless there's a compelling reaons to
do otherwise (e.g. interface with C or existing,
nonmodifiable code).

std::vector<std::vector> > arr2d;

std::vector<std::vector<int> > arr2d;

-Kevin
 
C

csx

Hi, and thanks so much! Ive looked at your array example in C, and it has
been very helpful.
However, there were a couple of things. In this function:

double **alloc2d(size_t rows, size_t cols)
{
double **result;
size_t row = 0;
size_t col = 0;
if(result = malloc(rows * sizeof *result))
{
if(*result = malloc(rows * cols * sizeof **result)
for(row = 1; row < rows; ++row)
result[row] = *result + row * cols;
else
{
free(result);
result = NULL;
}
}
return result;
}


There is a problem on the lines
if(result = malloc(rows * sizeof *result))
if(*result = malloc(rows * cols * sizeof **result)

There are the errors:
error C2440: '=' : cannot convert from 'void *' to 'double ** '
error C2440: '=' : cannot convert from 'void *' to 'double *'

Not sure how to fix these, can anyone provide advise?
Many 'Thanks' in advance!!
 
M

Mike Wahler

csx said:
Hi, and thanks so much! Ive looked at your array example in C, and it has
been very helpful.

First note that C is not C++. They look very similar
in syntax, the the semantics are different in many
cases. You've just discovered one example of this.

I referred you to that C code for ideas, not
as a 'drop in' C++ solution to your questions.

However, that code I wrote can be made valid C++ with
a simple 'fix'. (actually I'd call it a 'hack').

Or you can configure your compiler to compile
C instead of C++).

See below.
However, there were a couple of things. In this function:

double **alloc2d(size_t rows, size_t cols)
{
double **result;
size_t row = 0;
size_t col = 0;
if(result = malloc(rows * sizeof *result))
{
if(*result = malloc(rows * cols * sizeof **result)
for(row = 1; row < rows; ++row)
result[row] = *result + row * cols;
else
{
free(result);
result = NULL;
}
}
return result;
}


There is a problem on the lines
if(result = malloc(rows * sizeof *result))
if(*result = malloc(rows * cols * sizeof **result)

There are the errors:
error C2440: '=' : cannot convert from 'void *' to 'double ** '
error C2440: '=' : cannot convert from 'void *' to 'double *'

Those are indeed errors in C++, but not in C.
Not sure how to fix these, can anyone provide advise?
Many 'Thanks' in advance!!

Remember what I wrote:

"It uses the C functions 'malloc()' and 'free()' for
memory management, but you should be able to drop in
new[] and delete[] in their place -- you *must* do this
if you're creating arrays of types which have ctors/dtors,
or they won't get called."

I forgot to add "if you use 'malloc()' you'll need to
cast the return value to the target type"

C allows the conversion from/to 'void*' and any other
pointer type without a cast. But C++ requires a cast:

/* hack: */
if(result = (double**)malloc(rows * sizeof *result))
if(*result = (double*)malloc(rows * cols * sizeof **result)

I also wrote:
"But if you don't have to, don't use arrays. Use containers.
Really."

And I still stand by that advice.

-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,265
Latest member
TodLarocca

Latest Threads

Top