问题
I'm trying to get std input to scan in two 2d parallel arrays (arrAtk, arrDef) of x rows (x<100), and y columns (y<1,000,000). But y is a variable length in each row.
The first line of input is x for the number of rows in each array. the second line is y for the number of columns in the first row. Following that is y integers to be read into the arrAtk array. Then another y integers to be read into the arrDef array. Directly following is an int y for the number of columns in the next two rows. And so on.
The parallel arrays will hold integers that will be sorted later, and each parallel element will be compared to see which of the rows had higher numbers.
Problem: So I'm trying to scan the input with a function call and dynamically allocate the correct amount of memory and scan the input for each row of the 2d arrays. This seems to work okay but then when I try to print the array values in main it crashes. The printf statements work in the scanIn function so I must not be passing values correctly. How can I get it to where I can use the dynamically created arrays outside of the function?
Thanks in advance
Example of std input:
2 //<- x num of rows
2 //<- y num of cols
3
6
5
2
3 //<- y num of cols
2
3
12
9
3
4
CODE:
#include <stdio.h>
#include <stdlib.h>
int scanIn(int**,int**,int*);
int main(){
int cases, *armies, **arrAtk, **arrDef;
cases = scanIn(arrAtk,arrDef,armies);
printf("%d\n",arrAtk[1][2]); // Should be 12 with above input
printf("%d",arrDef[0][1]); // Should be 2
return 0;
}
int scanIn(int **arrAtk, int **arrDef, int *armies){
int i, j, cases;
scanf("%d",&cases);
arrAtk = (int**)malloc(sizeof(int*)*cases);
arrDef = (int**)malloc(sizeof(int*)*cases);
armies = (int*)malloc(sizeof(int)*cases);
for(i=0;i<cases;i++){
scanf("%d",&armies[i]);
arrAtk[i] = malloc(sizeof(int)*armies[i]);
arrDef[i] = malloc(sizeof(int)*armies[i]);
for(j=0;j<armies[i];j++){
scanf("%d",&arrAtk[i][j]);
}
for(j=0;j<armies[i];j++){
scanf("%d",&arrDef[i][j]);
}
}
return (cases);
}
回答1:
While there are better ways of doing this, it can be done with the approach you have taken. The first thing to note is you were passing each pointer to your function instead of the address of the pointer. When that occurs, your function receives a copy of the pointer, containing the proper address for the values (if initialized), but with a very different address of its own.
So when you allocate storage for each of your arrays in the function, the pointers in main
are completely unchanged. They still point to nothing. In order to have the allocations reflected in main
you must pass the address of the pointer to your function, and dereference accordingly in your function, so that the allocations are available in main
.
The short version is you need to call your function with scanIn (&arrAtk, &arrDef, &armies)
and your prototype must be (int***, int***, int**)
. (not particularly attractive)
One other issue is that style in C generally avoids the use of caMelCase
variables (leave that for C++). See: (section 2.2) NASA C Style Guide (Goddard Spaceflight Center 1994)
Below is an example of the additional level of indirection required to make the allocation work as you intended. (note: you should also free the memory you allocate):
#include <stdio.h>
#include <stdlib.h>
int scan_in (int***, int***, int**);
int main (void) {
int cases, *armies, **arr_atk, **arr_def;
cases = scan_in (&arr_atk, &arr_def, &armies);
printf ("\n cases : %d\n", cases);
printf (" arr_atk[1][2] : %d\n", arr_atk[1][2]);
printf (" arr_def[0][1] : %d\n\n", arr_def[0][1]);
return 0;
}
int scan_in (int ***arr_atk, int ***arr_def, int **armies)
{
int i, j, cases;
scanf ("%d",&cases);
*arr_atk = malloc (sizeof **arr_atk * cases);
*arr_def = malloc (sizeof **arr_def * cases);
*armies = malloc (sizeof *armies * cases);
for (i = 0; i < cases; i++) {
scanf ("%d", &(*armies)[i]);
(*arr_atk)[i] = malloc (sizeof ***arr_atk * (*armies)[i]);
(*arr_def)[i] = malloc (sizeof ***arr_def * (*armies)[i]);
for (j = 0; j < (*armies)[i]; j++) {
scanf ("%d", &(*arr_atk)[i][j]);
}
for (j = 0; j < (*armies)[i]; j++) {
scanf ("%d", &(*arr_def)[i][j]);
}
}
return (cases);
}
Input
$ cat ../dat/2dscan.txt
2
2
3
6
5
2
3
2
3
12
9
3
4
Output
$ ./bin/2dscanin < ../dat/2dscan.txt
cases : 2
arr_atk[1][2] : 12
arr_def[0][1] : 2
note: since you are new to C, there are a few more areas where you can improve your code: (1) always initialize your variables that are not explicitly assigned a value in your code; (2) always validate the return values from the functions you call; and (3) always keep track of, and free
the memory you allocate when it is no longer needed. Taking that into consideration, your main
and scan_in
code would look like:
int main (void) {
int i, cases = 0, *armies = NULL, **arr_atk = {NULL}, **arr_def = {NULL};
if ((cases = scan_in (&arr_atk, &arr_def, &armies)) < 1) {
fprintf (stderr, "error: invalid value for cases returned.\n");
return 1;
}
printf ("\n cases : %d\n", cases);
printf (" arr_atk[1][2] : %d\n", arr_atk[1][2]);
printf (" arr_def[0][1] : %d\n\n", arr_def[0][1]);
for (i = 0; i < cases; i++) { /* free allocated memory */
if (arr_atk[i]) free (arr_atk[i]);
if (arr_def[i]) free (arr_def[i]);
}
if (arr_atk) free (arr_atk);
if (arr_def) free (arr_def);
if (armies) free (armies);
return 0;
}
int scan_in (int ***arr_atk, int ***arr_def, int **armies)
{
int i, j, cases;
if (scanf ("%d",&cases) != 1) {
fprintf (stderr, "scan_in() error: input failure.\n");
return 0;
}
*arr_atk = malloc (sizeof **arr_atk * cases);
*arr_def = malloc (sizeof **arr_def * cases);
*armies = malloc (sizeof *armies * cases);
for (i = 0; i < cases; i++) {
if (scanf ("%d", &(*armies)[i]) != 1) {
fprintf (stderr, "scan_in() error: input failure.\n");
return 0;
}
(*arr_atk)[i] = malloc (sizeof ***arr_atk * (*armies)[i]);
(*arr_def)[i] = malloc (sizeof ***arr_def * (*armies)[i]);
for (j = 0; j < (*armies)[i]; j++) {
if (scanf ("%d", &(*arr_atk)[i][j]) != 1) {
fprintf (stderr, "scan_in() error: input failure.\n");
return 0;
}
}
for (j = 0; j < (*armies)[i]; j++) {
if (scanf ("%d", &(*arr_def)[i][j]) != 1) {
fprintf (stderr, "scan_in() error: input failure.\n");
return 0;
}
}
}
return (cases);
}
来源:https://stackoverflow.com/questions/35853776/c-passing-pointer-to-pointer-to-a-function-and-using-malloc