Jump to content

Passing a multidimensional array of structures to a function

- - - - -

  • Please log in to reply
4 replies to this topic

#1
DarkLordofthePenguins

DarkLordofthePenguins

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 409 posts
I'm writing a clone of Wumpus in C. It creates a grid of "caves" using a 2-dimensional matrix whose size is specified by the user. The elements of the matrix are structures of type cave. Each cave structure is either open (a cave) or closed (rock).

So far I have created structures for the player, the Wumpus, and the caves, I have gotten it to take the size and the number of levels as command line inputs from the user, and I have created a grid to represent one level. Now I want to create a function to initiate all the values associated with the grid, including the position of the player, Wumpus, and arrows, how much gold is in each cave, and which cave structures are open.

Here's the problem: The declaration for the matrix is

struct cave grid[size][size];


The function prototype I have is

void gridsetup( struct cave ** );


When I try to compile I get this error message:

wumpus.c:31: warning: passing argument 1 of ‘gridsetup’ from incompatible pointer type


Here is the entire source code. You don't have to read it all; I'm just putting it here for reference.

wumpus.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "wumpus.h"

#include "game.h"


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

	size = 5;

	levels = 10;

	help = false;


	// Begin get parameters

	for( int i = 1; i < argc; i++ ){

		if( (strcmp( argv[i], "-s" ) == 0) && argv[i+1] )

			size = atoi( argv[i+1] );

			// Determines the size of the grid

		else if( (strcmp( argv[i], "-l" ) == 0) && argv[i+1] )

			levels = atoi( argv[i+1] );

			// Determines the number of levels

		else if( strcmp(argv[i], "--help" ) == 0 ){

			help = true;

			displayhelp();

		}

	}

	// End get parameters


	if( help == true )  // Display help, then quit

		return 0;


	struct cave grid[size][size];

	gridsetup( grid );

	printf( "%d\n", grid[0][0].gold );


	return 0;

}


void displayhelp(){

	printf( "Proper usage: wumpus {-option value}\nOptions:\n-s: size of the playing grid\n-l: number of levels\n--help: Print this help information.\n" );

	// Uses BNF notation.

}


wumpus.h

#ifndef _WUMPUS_H_

#define _WUMPUS_H_


#include <stdbool.h>


int size;      // These variables are global so

int levels;    // I can use them in functions that

bool help;     // alter the game.


struct player{

	bool alive;

	int arrows;

	int gold;

	int x; // Longitude of player

	int y; // Latitude of player

};


struct wumpus{

	int x; // Longitude of Wumpus

	int y; // Latitude of Wumpus

};


struct cave{

	bool open;

	int gold;

	int arrow;

};


enum direction{ north, south, east, west };


void displayhelp( void );


#endif


game.c

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include "wumpus.h"

#include "game.h"


void gridsetup( struct cave **grid ){

	grid[0][0].open = true;

	grid[0][0].gold = 2;

}


game.h

#ifndef _GAME_H_

#define _GAME_H_


void gridsetup( struct cave ** );


#endif


I've already tried using struct cave grid[][] in the function declaration and it didn't work. I tried dynamically allocating memory for it will malloc, but I got a segfault.

Is there any way to pass an array of structures to a function? I can't find anything on it in either K&R or C in a Nutshell, and I've Googled the error messages and only found instructions to do things that I've already tried.

If nothing else works, I will make a 3-dimensional array and do all the initialization in the main function (which is undesirable as I'm trying to make the program as modular as possible).
Programming is a journey, not a destination.

#2
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
You should look at this C FAQ Question. This isn't just a pointer to a pointer, it's a pointer to an array, which is different and can be annoying as you must include the size of the second dimension. Rewrite your code like this and see:
#ifndef _GAME_H_

#define _GAME_H_


#include "wumpus.h"


void gridsetup( struct cave (*)[size] );


#endif
void gridsetup( struct cave (*grid)[size] ){

	grid[0][0].open = true;

	grid[0][0].gold = 2;

}

Wow I changed my sig!

#3
DarkLordofthePenguins

DarkLordofthePenguins

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 409 posts
Yes, that works. Thank you. I didn't know you could use a variable in a function declaration like that. Still, I'm confused as to how a pointer to an array is different from a pointer to a pointer, seeing as arrays are accessed through pointers. It seems to work that way with the parameters of the main() function, though it may be something that only works for strings, I suppose.
Programming is a journey, not a destination.

#4
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
Well, it works fine for dynamically allocated arrays. :)
    struct cave **grid = (struct cave **) malloc(size * sizeof(struct cave *));


    for (int i = 0; i < size; ++i)

    {

        grid[i] = (struct cave *) malloc(size * sizeof(struct cave));

    }


	gridsetup( grid );
The problem being that struct cave ** is only a single dynamically allocated array of dynamically allocated struct caves. In order to have a two dimensional array of dynamically allocated struct caves, you'll need three stars. :)
struct cave ***grid = (struct cave ***) malloc(size * sizeof(struct cave ***));


    for (int i = 0; i < size; ++i)

    {

        grid[i] = (struct cave **) malloc(size * sizeof(struct cave **));

        for (int j = 0; j < size; ++j)

        {

            grid[i][j] = (struct cave *) malloc(sizeof(struct cave));

        }

    }


	gridsetup( grid );
The rest of your code would have to be updated accordingly.
Wow I changed my sig!

#5
xetama

xetama

    Newbie

  • Members
  • Pip
  • 9 posts

Quote

I tried dynamically allocating memory for it will malloc, but I got a segfault.
The segfault was probably a result of trying to use a grid[0][0] after calling something like (cave**)malloc(sizeof(cave)*size*size);




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users