Link to home
Create AccountLog in
Avatar of David Sankovsky
David SankovskyFlag for Israel

asked on

using pointers to pointers to write to a two dimensional array

Hi Fellas, I'm having some trouble with the following code. I'm trying to initiate a two dimensional array of chars with spaces using pointers and I keep getting an error, could you please help me figure out what I'm doing wrong?
#define _CRT_SECURE_NO_WARNINGS
/*-------------------------------------------------------------------------
  Include files:
--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdbool.h>


/*=========================================================================
  Constants and definitions:
==========================================================================*/

/* put your #defines and typedefs here*/

#define ROWS 10
#define COLS 10
#define SUBS_NUM 4

void CreateBattlefieldwithpointers(char** Array) {
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			*(Array[i] + j) = ' ';
		}
	}
}

void PrintBattlefield (char battlefield[ROWS][COLS]) {
    for (int i=0, inum=ROWS-1 ; i<ROWS ; i++, inum--) {
        printf("%d | ",inum);
        for (int j=0, jnum=0 ; j<COLS ; j++, jnum++) {
            printf("%c ",battlefield[i][j]);
        }
        printf("\n");
    }
    printf("    - - - - - - - - - - \n    0 1 2 3 4 5 6 7 8 9 \n");
}

int main()
{
    char PlayerTable[ROWS][COLS], CompTable[ROWS][COLS];
    char** PT = &PlayerTable[0], CT = &CompTable[0];
    CreateBattlefieldwithpointers(&PT);
    PrintBattlefield(PlayerTable);
	 

    return 0;
}

Open in new window


I use the printing method with direct array pass intentionally for now, until I can get why I can't initialize the array the way I need.
Avatar of Karrtik Iyer
Karrtik Iyer
Flag of India image

Can you please post what error are you getting? Is it a compilation error or runtime error?
Avatar of David Sankovsky

ASKER

runtime. Memory Access violation.
When trying to populate the array with spaces, I don't even get to the printing.
I think you need to have your print function parameters like below :
void PrintBattlefield (char* battlefield[COLS])

Or
void PrintBattlefield (char battlefield[][COLS])


Karrtik Iyer
Expert Comment 2015-12-20 at 17:08:23ID: 41378736
I think you need to have your print function parameters like below :
void PrintBattlefield (char* battlefield[COLS])

Or
void PrintBattlefield (char battlefield[][COLS])

As I wrote above, the printing works fine, it's the populating function that throws the error.
Here is how I did it:
#define _CRT_SECURE_NO_WARNINGS
/*-------------------------------------------------------------------------
Include files:
--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdbool.h>
#include <cstdio>

/*=========================================================================
Constants and definitions:
==========================================================================*/

/* put your #defines and typedefs here*/

#define ROWS 10
#define COLS 10
#define SUBS_NUM 4

void CreateBattlefieldwithpointers(char **&Array) {
	Array = new char*[ROWS];
	for (int i = 0; i < ROWS; i++) {
		Array[i] = new char[COLS];
		for (int j = 0; j < COLS; j++) {
			Array[i][j] = ' ';
		}
	}
}

void PrintBattlefield(char **&battlefield) {
	for (int i = 0, inum = ROWS - 1; i<ROWS; i++, inum--) {
		printf("%d | ", inum);
		for (int j = 0, jnum = 0; j<COLS; j++, jnum++) {
			printf("%c ", battlefield[i][j]);
		}
		printf("\n");
	}
	printf("    - - - - - - - - - - \n    0 1 2 3 4 5 6 7 8 9 \n");
}

int main()
{
	char** PlayerTable;
	CreateBattlefieldwithpointers(PlayerTable);
	PrintBattlefield(PlayerTable);

	std::getchar();
	return 0;
}

Open in new window

Produces the following output -User generated image-saige-
ASKER CERTIFIED SOLUTION
Avatar of Karrtik Iyer
Karrtik Iyer
Flag of India image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of phoffric
phoffric

Here is one way to force your **Array to represent your known ROWS x COLS array in main(). In this approach, you are relying on your knowledge of the way C arranges its rows and columns in memory.
https://en.wikipedia.org/wiki/Row-major_order

#define _CRT_SECURE_NO_WARNINGS
/*-------------------------------------------------------------------------
Include files:
--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdbool.h>


/*=========================================================================
Constants and definitions:
==========================================================================*/

/* put your #defines and typedefs here*/

#define ROWS 10
#define COLS 10
#define SUBS_NUM 4

void CreateBattlefieldwithpointers(char** Array) {
	char* array1d = (char*)Array;  // alias for a 1d array
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			array1d[i*COLS + j] = 'A' + i + j; // for debug; change to space
		}
	}
}

void PrintBattlefield(char battlefield[ROWS][COLS]) {
	for (int i = 0, inum = ROWS - 1; i < ROWS; i++, inum--) {
		printf("%d | ", inum);
		for (int j = 0, jnum = 0; j < COLS; j++, jnum++) {
			printf("%c ", battlefield[i][j]);
		}
		printf("\n");
	}
	printf("    - - - - - - - - - - \n    0 1 2 3 4 5 6 7 8 9 \n");
}

int main()
{
	char PlayerTable[ROWS][COLS];
	char** PT = (char**)PlayerTable;
	CreateBattlefieldwithpointers(PT);
	PrintBattlefield(PlayerTable);

	return 0;
}

Open in new window

@it_saige,
Your solution appears to be written for the C++ zone. Note that the provided code is C99 and the zone is C.
@Karrtik Iyer,
>>  I do not think the code you posted in your question compiles, please see screenshot below for errors.

This C99 code compiles and builds without errors. Change your .cpp extension to .c. If that still does not work, then download VS 2015 and build the author's OP code from there.

(Note: The C99 compiler gives warnings which should be eliminated. See my post for one approach.)
If you prefer the more conventional Array[ i ][ j ] approach, you can do it this way (the typedef makes it a bit clearer):
#define _CRT_SECURE_NO_WARNINGS
/*-------------------------------------------------------------------------
Include files:
--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdbool.h>


/*=========================================================================
Constants and definitions:
==========================================================================*/

/* put your #defines and typedefs here*/

#define ROWS 10
#define COLS 10
#define SUBS_NUM 4

typedef char One_Row_t[COLS]; // define a type that is a row of COLS char elements

void CreateBattlefieldwithpointers(One_Row_t Array[ROWS]) {
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			Array[ i ][ j ] = 'A' + i + j;  // for debug; change to space

		}
	}
}

void PrintBattlefield(char battlefield[ROWS][COLS]) {
	for (int i = 0, inum = ROWS - 1; i < ROWS; i++, inum--) {
		printf("%d | ", inum);
		for (int j = 0, jnum = 0; j < COLS; j++, jnum++) {
			printf("%c ", battlefield[ i ][ j ]);
		}
		printf("\n");
	}
	printf("    - - - - - - - - - - \n    0 1 2 3 4 5 6 7 8 9 \n");
}

int main()
{
	char PlayerTable[ROWS][COLS];
	One_Row_t* PT = (One_Row_t*)PlayerTable;
	CreateBattlefieldwithpointers(PT);
	PrintBattlefield(PlayerTable);

	return 0;
}

Open in new window

This version just changes the CreateBattlefieldwithpointers api in an equivalent manner to my previous post by changing the array, [], symbol to a pointer symbol, *.
#define _CRT_SECURE_NO_WARNINGS
/*-------------------------------------------------------------------------
Include files:
--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdbool.h>


/*=========================================================================
Constants and definitions:
==========================================================================*/

/* put your #defines and typedefs here*/

#define ROWS 10
#define COLS 10
#define SUBS_NUM 4

typedef char One_Row_t[COLS]; // define a type that is a row of COLS char elements

void CreateBattlefieldwithpointers(One_Row_t *Array) {
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			Array[i][j] = 'A' + i + j;
		}
	}
}

void PrintBattlefield(char battlefield[ROWS][COLS]) {
	for (int i = 0, inum = ROWS - 1; i < ROWS; i++, inum--) {
		printf("%d | ", inum);
		for (int j = 0, jnum = 0; j < COLS; j++, jnum++) {
			printf("%c ", battlefield[i][j]);
		}
		printf("\n");
	}
	printf("    - - - - - - - - - - \n    0 1 2 3 4 5 6 7 8 9 \n");
}

int main()
{
	char PlayerTable[ROWS][COLS];
	One_Row_t* PT = (One_Row_t*)PlayerTable;
	CreateBattlefieldwithpointers(PT);
	PrintBattlefield(PlayerTable);

	return 0;
}

Open in new window

@Karrtik Iyer,
Nothing wrong with this (and it easier to deal with):
>>   //char** PT = &PlayerTable[0], CT = &CompTable[0];
>>      CreateBattlefieldwithpointers(PlayerTable);

But since the author already demonstrated his ability to handle 2d arrays by virtue of his success with: PrintBattlefield(PlayerTable), then I interpreted his request as asking for assistance when we always have pointers in play when calling CreateBattlefieldwithpointers().
To my eye, the initial error was:

CreateBattlefieldwithpointers(&PT);

Open in new window


When the subroutine code you wrote would have expected you to call

CreateBattlefieldwithpointers(PT);

Open in new window


i.e. without the ampersand.

=====

But I think your code would be clearer if you simply used the same notation throughout instead of exploiting the ability to alias things.
@jmcg,
>> i.e. without the ampersand.
Your post identifies one of the warnings (i.e., PT is char**, but the extra & means the argument passed in is char***); but your comment does not address the functional problem.

The author's OP has
void CreateBattlefieldwithpointers(char** Array) {
...
			*(Array[ i ] + j) = ' ';

Open in new window

But Array[ i ] is not defined as the author intended (i.e., the author intends that Array[ i ] be the address of the start of the i_th row, but that is not the case, since the compiler was given no information about the number of elements in each row of this 2d array.

You should ask yourself what is the difference of the addresses of, say, Array[3] and Array[2], as defined in the OP. The intention by the author is that the difference should by COLS bytes, but instead it is only the number of bytes in a pointer.

Hope that helps clarify the main issue.
Simple and working. it got me going in the right direction. Thanks for everyone for participating.
If everyone helped you, then you should split points across every post that helped you better understand the concepts and issues that you faced. Do you know how to do that?