2016-03-07 2 views
1

Я пытаюсь получить зЬй вход для сканирования в двух параллельных 2d массивов (arrAtk, arrDef) от х строк (х < 100), а у столбцов (y < 1,000,000). Но y - это переменная длина в каждой строке.C Передача Указатель на указатель на функцию и использование таНоса

Первая строка ввода: x для количества строк в каждом массиве. Вторая строка: y Число столбцов в первой строке. После этого y целые числа, которые нужно прочитать в массиве arrAtk. Затем еще y целые числа для чтения в массив arrDef. Непосредственно следующее: int y для количества столбцов в следующих двух строках. И так далее.

Параллельные массивы будут содержать целые числа, которые будут отсортированы позже, и каждый параллельный элемент будет сравниваться, чтобы увидеть, какая из строк имела более высокие цифры.

Проблема: Поэтому я пытаюсь выполнить сканирование ввода с помощью вызова функции и динамически выделять правильный объем памяти и проверять ввод для каждой строки 2-мерных массивов. Кажется, что все работает нормально, но затем, когда я пытаюсь напечатать значения массива в главном, он сработает. Операторы printf работают в функции scanIn, поэтому я не должен правильно передавать значения. Как я могу получить его туда, где я могу использовать динамически созданные массивы вне функции?

Заранее спасибо

Пример станд ввода:

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 

КОД:

#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); 
} 
+2

Вам нужно пересмотреть первую строку 'main', и помните, что C * использует передачу по значению *. Запись 'arrAtk =' внутри 'scanIn' не повлияет на' arrAtk' в 'main'. (На самом деле было бы неплохо использовать разные имена переменных для параметров в 'scanIn', чтобы избежать умственного объединения двух переменных) –

+1

В вашем коде есть несколько ошибок, которые будут генерировать сообщения компилятора. Прежде чем пытаться запустить программу, вы должны исправить все сообщения компилятора. (Не попадайте в ловушку, думая, что сообщение, содержащее слово «предупреждение», на самом деле не является ошибкой) –

+2

Слово «double» относится к типу с плавающей точкой, поэтому «двойной указатель» будет иметь тип ' двойной * '. Используйте «указатель на указатель», а не «двойной указатель». –

ответ

1

Хотя есть лучшие способы сделать это, это может быть сделано с подход, который вы приняли. Первое, что нужно отметить, - это передать каждый указатель на свою функцию вместо адреса указателя. Когда это произойдет, ваша функция получает копию указателя, содержащего правильный адрес для значений (если они были инициализированы), но с совсем другой адрес.

Поэтому, когда вы выделяете хранилище для каждого из ваших массивов в функции, указатели в main полностью не изменяются. Они все еще ничего не говорят. Для того чтобы распределения, отраженные в main, вы должны передать адрес указатель на вашу функцию и разыменовать соответствующую функцию, чтобы распределения были доступны в main.

Короткий вариант - вам нужно позвонить вашей функции с помощью scanIn (&arrAtk, &arrDef, &armies), а ваш прототип должен быть (int***, int***, int**). (не особенно привлекательно)

Еще одна проблема заключается в том, что стиль в C обычно избегает использования переменных caMelCase (оставьте это для C++). См.: (Раздел 2.2) NASA C Style Guide (Goddard Spaceflight Center 1994)

Ниже приведен пример дополнительного уровня косвенности, необходимого для выполнения работы по размещению, как вы планировали. (Примечание: вы должны также освободить память вы выделить):

#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); 
} 

Вход

$ cat ../dat/2dscan.txt 
2 
2 
3 
6 
5 
2 
3 
2 
3 
12 
9 
3 
4 

Выход

$ ./bin/2dscanin < ../dat/2dscan.txt 

cases   : 2 
arr_atk[1][2] : 12 
arr_def[0][1] : 2 

примечание: поскольку вы новичок в C , есть еще несколько областей, где вы можете улучшить свой код: (1) всегда инициализирует свои переменные, которые явно не назначают значение в вашем коде; (2) всегда проверяют возвращаемые значения из функций, которые вы вызываете; и (3) всегда отслеживает и free память, которую вы выделяете, когда она больше не нужна. Принимая это во внимание, ваш main и scan_in код будет выглядеть следующим образом:

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); 
} 
Смежные вопросы