2013-09-14 2 views
2

Я пытаюсь читать целые числа из файла один за другим и читать его в программе в виде строки & номер столбца.C - Чтение строки за строкой из файла - отображается неправильный вывод

Моего содержимого файла:

3 
2 1 
2 2 
2 3 

И мой код:

fgets(line, 2, fp); 
livecells = atoi(line); 
fprintf(stderr, "\n%i live cells\n", livecells);  

while (!feof(fp)) 
{ 
    fgets(line, 5, fp); 

    alive_row = atoi(&line[0]); 
    alive_column = atoi(&line[2]); 

    fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);  
} 

где строка является массивом символов (строка), где хранится содержимое fgets и alive_row, & alive_column является целыми числа ,

Но по какой-то причине выход равен:

3 live cells 

Cell: (0)(0) 
Cell: (2)(1) 
Cell: (2)(2) 
Cell: (2)(3) 
Cell: (2)(3) 

Проблема в том, почему это первая ячейка распечатанной (0) (0)? Я не знаю, почему это печатается ... Извините, если это ослепительно очевидно ...

EDIT: И, очевидно, повторная ячейка (2) (3) в конце, oops.

+2

Первая колонка печатается как '(0, 0) ', потому что' atoi' терпит неудачу и он возвращает 0. Пожалуйста, не используйте 'atoi', а скорее используйте' strtol', который заставит вас включить, чтобы проверить, было ли преобразование успешным или нет. –

ответ

3

Первый столбец напечатан как (0, 0), потому что atoi терпит неудачу. Пожалуйста, не используйте atoi, а используйте strtol, что позволит вам проверить, было ли успешным преобразование.

Причина atoi терпит неудачу, потому что у вас есть дополнительный \n характер, потому что с fgets(fgets(line, 2, fp); вы читаете только один символ - потому что вы прошли 2 для размера буфера, и один элемент из буфера резервируется для \0 характера , Просто используйте достаточно большой буфер для чтения всей строки и передайте размер буфера.

Чтобы исправить другую ошибку, просто не используйте feof. Скорее проверьте возвращаемое значение fgets, чтобы узнать, сколько символов он читает из файла (или, если вы действительно хотите использовать feof, выполните эту проверку после вызова fgets).

while ( fgets(line, sizeof(line), fp) > 0) 
{ 
    char* end; 

    alive_row = strtol(&line[0], &end, 10); 

    // If the end points to the &line[0], then no 
    // characters were converted!  
    if(end == &line[0]) 
    { 
     printf("strtol failed!\n"); 
     return 0; 
    } 

    alive_column = strtol(&line[2], &end, 10); 

    // If the end points to the &line[2], then no 
    // characters were converted!  
    if(end == &line[2]) 
    { 
     printf("strtol failed!\n"); 
     return 0; 
    } 

    fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);  
} 

У нас есть чек &line[0] == end, потому что второй аргумент, переданный strtol является

Ссылка на объект типа полукокса *, значение которого задается с помощью функции к следующему символу ул после численная величина.

Если в строке не было числового значения, этот указатель укажет на начало строки, которую вы пытались преобразовать.

Если вы не знаете, если число цифр будет 1 или 2, или любой, вы все еще можете использовать strtol, чтобы помочь вам здесь:

while ( fgets(line, sizeof(line), fp) > 0) 
{ 
    char* end; 
    char* tmp; 

    alive_row = strtol(&line[0], &end, 10); 

    // If the end points to the &line[0], then no 
    // characters were converted!  
    if(end == &line[0]) 
    { 
     printf("strtol failed!\n"); 
     return 0; 
    } 

    // If the previous strtol converted the first number 
    // end will point to the space character (the first character after the number). 
    // So, just pass 
    // end + 1 which should point to the second number 
    tmp = end + 1; 
    alive_column = strtol(tmp, &end, 10); 

    // If the end points to the tmp, then no 
    // characters were converted!  
    // (this is why we used this tmp to place end + 1 - we need to 
    // check for the success of the strtol). 
    if(end == tmp) 
    { 
     printf("strtol failed!\n"); 
     return 0; 
    } 

    fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);  
} 
+0

Хорошо, не используйте atoi, использовали strtol: alive_row = strtol (& line [0], NULL, 10); alive_column = strtol (& line [2], NULL, 10); но выход остается неизменным? –

+0

Чтобы проверить фактическую ошибку, вам нужен второй аргумент, а не NULL. Второй аргумент будет указывать на нераскрытую оставшуюся часть строки. Strtol будет указывать на сбой, если этот указатель совпадает с указателем начала, который вы ему передали (если символы не были преобразованы). –

+0

Все еще путают по этому поводу, извините. Итак, что вы говорите, что NULL нужно изменить? –

0

fgets() читает символ \n, если возможно.
Если нет, то \n будет прочитан в следующей операции чтения.

Поскольку ваш звонок fgets(line, 2, fp);, считывается только 1 символ, а второй заполняется нулевым символом. Итак: line [0] == '3' и строка [1] == '\ 0'.

Конец строки будет прочитан позже, поэтому ваша операция первого чтения внутри цикла while() такова: "\n". Это приводит к произвольным результатам с atoi (нули в вашем случае).

Примите во внимание, что:

fgets (линия, N, Fp) считывает из файла FP, не более N - 1 символов из стандартного ввода, в том числе \ п, если это возможно. Результат ставится в очередь, и ALWAYS делает номер в конце для символа \ 0.

1

Поскольку вы имеете дело ментов однозначных цифр вы просто используйте line[0]-'0' для преобразования строки [0] в целое число. при первом сканировании просто сканируйте 5 байтов, чтобы поток файлов переместился на следующую строку.

#include<stdio.h> 

    int main() 
    { 

    FILE *fp; 
    int alive_row; 
    int alive_column,livecells; 


    char line[10]; 
    fp=fopen("file1","r"); 
    fgets(line,5 , fp); 
    livecells = line[0]-'0'; 
    fprintf(stderr, "\n %i live cells\n", livecells); 

    while (fgets(line, 5, fp)!=NULL) 
    { 
    // puts(line); 
     alive_row = line[0]-'0'; 
     alive_column = line[2]-'0'; 

     fprintf(stderr,"\n Cell: (%i)(%i)\n", alive_row, alive_column); 
    } 
    fclose(fp); 
    } 

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

файл1:

12 
2 1 
2 2 
2 3 
50 5 
30 20 
5 30 
30 330 
3390 447 
12 1234 
0 0 
1234 1 
154 0 

КОД:

#include<stdio.h> 
#include<string.h> 

int main() 
{ 

    FILE *fp; 
    int alive_row=0;  
    int alive_column=0,livecells; 
    int column=0,i; 

    char line[10]; 
    fp=fopen("file1","r"); 
    fgets(line,5, fp);  //read first line 
    livecells = atoi(line); //convert into int 
    fprintf(stderr, "\n %i live cells\n", livecells); 

    while (fgets(line, 12, fp)!=NULL)  //read next lines 
     { 
     for(i=0;i<strlen(line)-1;i++)  //loop to separate rows and columns , here if space occurs make flag column as 1 
      { 
      if(line[i]!=' ' && column!=1)  
      alive_row = 10*alive_row+line[i]-'0'; //convert into integers 
      else 
       { 
       if(line[i]==' ') 
       i=i+1; 
       alive_column=10*alive_column+line[i]-'0'; 
       column=1; //you can write this statement just above if but you need to add two brace 
       } 
      } 

     printf(" Cell:(%d)(%d)\n\n", alive_row, alive_column); 
     alive_row=0; //after every iteration just make these value to default. 
     alive_column=0; 
     column=0; 
     } 
    fclose(fp); 
} 

ВЫХОД

12 live cells 

Cell:(2)(1) 

Cell:(2)(2) 

Cell:(2)(3) 

Cell:(50)(5) 

Cell:(30)(20) 

Cell:(5)(30) 

Cell:(30)(330) 

Cell:(3390)(447) 

Cell:(12)(1234) 

Cell:(0)(0) 

Cell:(1234)(1) 

Cell:(154)(0) 
+0

А что если строка содержит '55 21'? –

+0

Извините, забыл упомянуть не только одинарных цифрах, но и до двух цифр для каждого номера строки/столбца. –

+0

Прочитайте 10 байт с помощью fgets, а затем до перехода пространства в live_row и next alive_column ...line = "55 21" и ** alive_row = 10 * (строка [0] - '0') + (строка [1] - '0') ** и ** alive_column = 10 * (строка [3] - ' 0 ') + (строка [4] -' 0 ') ** или просто используйте strtok для проливания пространства разделителя, а затем strtol для преобразования в строки и столбцы – Gangadhar

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