David Sankovsky
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?
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.
#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;
}
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.
Can you please post what error are you getting? Is it a compilation error or runtime error?
ASKER
runtime. Memory Access violation.
When trying to populate the array with spaces, I don't even get to the printing.
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])
void PrintBattlefield (char* battlefield[COLS])
Or
void PrintBattlefield (char battlefield[][COLS])
ASKER
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;
}
Produces the following output --saige-
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
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
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;
}
@it_saige,
Your solution appears to be written for the C++ zone. Note that the provided code is C99 and the zone is C.
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.)
>> 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;
}
This version just changes the CreateBattlefieldwithpoint ers 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;
}
@Karrtik Iyer,
Nothing wrong with this (and it easier to deal with):
>> //char** PT = &PlayerTable[0], CT = &CompTable[0];
>> CreateBattlefieldwithpoint ers(Player Table);
But since the author already demonstrated his ability to handle 2d arrays by virtue of his success with: PrintBattlefield(PlayerTab le), then I interpreted his request as asking for assistance when we always have pointers in play when calling CreateBattlefieldwithpointers().
Nothing wrong with this (and it easier to deal with):
>> //char** PT = &PlayerTable[0], CT = &CompTable[0];
>> CreateBattlefieldwithpoint
But since the author already demonstrated his ability to handle 2d arrays by virtue of his success with: PrintBattlefield(PlayerTab
To my eye, the initial error was:
When the subroutine code you wrote would have expected you to call
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.
CreateBattlefieldwithpointers(&PT);
When the subroutine code you wrote would have expected you to call
CreateBattlefieldwithpointers(PT);
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
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.
>> 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) = ' ';
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.
ASKER
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?