2015-05-28 2 views
1

Я искал и читал какое-то время, и я не понимаю, почему это не сработает.Передача 2d массивов по ссылке в C

Я передаю массив 2d, используя &, чтобы передать адрес первого места в памяти. Функция принимает char *tokens указатель на эту ячейку памяти.

Функция:

void printOutput(FILE* template, char* tokens) 
{ 
    char c = fgetc(template); 

    while(c != EOF) 
    { 
     if(c != '$') 
     { 
      printf("%c", c); 
     } 
     else 
     { 
      c = fgetc(template); 
      int charVal = c-'0'; 

      if(charVal >= 0 && charVal <= 9) 
      { 
       printf("%d" , charVal); 
       printf("%s" , tokens[charVal]); 
      } 
     } 
     c = fgetc(template); 
    } 
    printf("\n\n"); 
} 

Функция вызывается так:

printOutput(template, &tokens[0]); 

Если я ставлю код функции в основной функции вместо вызова на printOutput функции, выход правильно отображается.

Из чего я могу сказать, что где-то между вызовом функции и функционирующей функцией происходит что-то, что превращает мой tokens[][] в массив всех (null).

Я считаю, что я обращаюсь к нему неправильно и надеюсь, что кто-то может помочь. При необходимости я могу предоставить больше кода.

Я очень ценю любую помощь!

Из-за ответов, помогающих, но все же не решая проблему, я прибегаю к добавлению функции main() из своего кода.

int main(int argc, char *argv[]) 
{ 
FILE *template = NULL; 
FILE *data = NULL; 

char input[INPUT_LENGTH]; 

template = fopen("template.txt", "r"); 
if (template != NULL) 
{ 
    data = fopen("data.txt", "r"); 
    if (data != NULL) 
    { 

     char input[INPUT_LENGTH]; 

     while (fgets(input, INPUT_LENGTH, data)) 
     { 
      char *token = NULL; 
      char *tokens[INPUT_LENGTH][FIELD_LENGTH]; 

      int pos = 0; 
      token = strtok(input, "|"); 
      while(token != NULL) 
      { 
       tokens[pos][0] = token; 
       token = strtok(NULL, "|"); 
       pos++; 
      } 

      printOutput(template, tokens[INPUT_LENGTH][FIELD_LENGTH]); 

      rewind(template); 
     } 

     fclose(data); 
    } 

    fclose(template); 
} 

return EXIT_SUCCESS; 

}

только теперь я могу взять на себя вопрос имеет отношение к char *tokens[INPUT_LENGTH][FIELD_LENGTH]; декларации, но я совершенно не уверен в этой точке.

+2

Каков тип 'токенов' на сайте вызова? – immibis

+1

fgetc() фактически возвращает int. EOF - это int. поэтому сравнение char с int не будет работать должным образом. Предложите сменить 'char c' на 'int c' – user3629249

+0

. Выведенный код несовместим с тем, какой символ в файле читается каждым fgetc(). предлагая управлять циклом «while» (EOF! = (c = fgetc (template)) », и удаление всех других вызовов в fgetc() – user3629249

ответ

5

Ваш 2D массив char tokens[X][LEN] выложена в памяти как:

Value  : Mem addresses for char[LEN] 

tokens[0] :   0 . . . LEN-1 
tokens[1] :  LEN . . . 2*LEN-1 
tokens[X-1] : (X-1)*LEN . . . X*LEN - 1 

Наоборот, char* tokens интерпретируется как:

Value  : Mem addresses for char 

tokens[0] : 0 
tokens[1] : 1 
tokens[2] : 2 

Теперь, когда вы передаете их в printf с форматом строки, вы 'разыменовывая значение до char, а не char*, как он ожидает. Следовательно, плохое выходное/неопределенное поведение.

Даже если вы взяли адрес (printf("%s" , &tokens[charVal]);), он все равно не даст вам ожидаемого результата, потому что он разрешает неправильный адрес.

Поскольку ваш 2D массив имеет фиксированный размер, вы должны объявить функцию как это:

void printOutput(FILE* template, char tokens[X][LEN]) 

Где X и LEN являются два измерения массива, очевидно ... В случае, если это не было ясно после того, как мое плотное использование их выше =)

Таким образом, компилятор точно знает, как интерпретировать tokens[charVal], который будет типом массива, который распадается на char*.


[Редактировать, поскольку вы предоставили дополнительную информацию и код]

Вы до сих пор путаюсь между char* и char с массивами. Я исправил это, так как tokens должен быть одномерным массивом char*.

 char *tokens[INPUT_LENGTH] = { 0 }; 

     int pos = 0; 
     token = strtok(input, "|"); 
     while(token != NULL) 
     { 
      tokens[pos] = token; 
      token = strtok(NULL, "|"); 
      pos++; 
     } 

     printOutput(template, tokens); 

Кроме того, printOutput должен быть определен как:

void printOutput(FILE* template, char** tokens) 
+0

, это начинает решать проблему, но токены [] [] все еще содержат нулевые значения. Я редактирую, чтобы включить main. –

+0

Я отредактировал свой ответ, поскольку вы предоставили код. В вашей программе могут быть другие проблемы. Я только что обратился к сразу очевидным. – paddy

1

Из следующего утверждения PRINTF внутри printOutput(), я полагаю, вы пытаетесь получить доступ к лексемы, как будто это массив строк. printf ("% s", токены [charVal]);

Но вы указали токены как указатель на char в printOutput(), который может в лучшем случае иметь только stand-in для массива символов (или, другими словами, всего одну строку, если она завершена нулем).

Либо вы должны объявить его как двойной массив размерности

void printOutput (FILE* template, char tokens[MAX_STRINGS] [MAX_CHARS_IN_STRING]) 

Или объявить его как указатель на массив символов

void printOutput (FILE* template, char (*tokens) [MAX_CHARS_IN_STRING]) 

и называют его

printOutput(template, tokens); 
-1

Вы передаете токены как «char», однако то, что вы пытаетесь сделать, это передать «char **», а именно указатель t o первый элемент в вашем 2D-массиве.

Попробуйте это:

void printOutput(FILE* template, char** tokens) 

И называют его следующим образом:

printOutput(template, tokens); 

Обратите внимание, что вы хотите все 'символ *' в токенов иметь '\ 0'.

например. маркеры [0] = {'a', 'b', 'c', '\ 0'} или токены [0] = "abc" , так как printf не знает, где остановиться Печать '% s'otherwise

+1

«char **» - это указатель на указатель на символ 'char'. Это не указатель на массив символов« 2D », который будет выглядеть так:' char (* p) [x] [y] '. – alk

Смежные вопросы