Ошибка программирования fscanf на C - PullRequest
0 голосов
/ 10 декабря 2011

Я пытаюсь прочитать из файла, который имеет значения, разделенные запятыми, например так (5-е поле должно иметь только r / b / n, а 6-е поле это y / n:

531,A,10,10,b,n,96.00,100.00
531,B,15,15,b,n,144.00,0.00
531,C,20,20,b,n,192.00,0.00
533,A,11,11,r,n,123.20,100.00
533,B,22,22,r,n,246.40,0.00

У меня есть следующееБлок кода fscanf для анализа файла построчно и сохранения значений в массиве, который я изменяю / выводю позже.

while(fscanf(data, "%4[0-9],%[A-Z],%3[0-9],%3[0-9],[prb],[yn],%d,%d\n", &house[i], room[i], &length[i], &width[i], paintcode[i], ceilingcode[i], &cost[i], &setupcost[i]) != EOF) {
   printf("%d,%c,%d,%d,%c,%c,%.2lf,%.2lf\n", &house[i], room[i], &length[i], &width[i], paintcode[i], ceilingcode[i], &cost[i], &setupcost[i]);
   i++;
}

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

main() {
   FILE *data;
   int house[200];
   char room[200];
   int length[200];
   int width[200];
   char paintcode[200];
   char ceilingcode[200];
   double cost[200];
   double setupcost[200];
   char line;
   int MAX_BUFF = 200;
   char x[200];
   double price[100];
   int i = 0, num_records = 0;

   data = fopen("quotes.data","r");
   if(data == NULL){
      printf("Error: file can't be open..\n");
   } else {
      while(fscanf(data, "%4[0-9],%[A-Z],%3[0-9],%3[0-9],[prb],[yn],%d,%d\n", &house[i], room[i], &length[i], &width[i], paintcode[i], ceilingcode[i], &cost[i], &setupcost[i]) != EOF) {
         printf("%d,%c,%d,%d,%c,%c,%.2lf,%.2lf\n", &house[i], room[i], &length[i], &width[i], paintcode[i], ceilingcode[i], &cost[i], &setupcost[i]);
         i++;
      }
      fclose(data);

Ответы [ 3 ]

1 голос
/ 10 декабря 2011

Здесь довольно много проблем.

Для начала семейство scanf вернет EOF только в случае сбоя чтения без получения любых входных значений.Если вы успешно получите некоторые, но не все, вы получите счетчик успешно отсканированного номера (включая случай, когда вы их все получили).

Вам также необходимо передать адрес переменных, которые вы хотите заполнить, что вы не сделали для всех из них.

Кроме того, спецификатор формата, такой как %4[0-9], будет читать символов, не одно целое число, поэтому потребуется буфер символов, а не адрес целого числа, как у вас.Если вы хотите заполнить целое число, вам нужно использовать что-то вроде %4d.

На фронте %[A-Z] они фактически создают строку с нулевым символом в конце, поэтому вам нужно выделить для этого место.

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

И, наконец,printf требует адреса только для строковых аргументов.

Следующая программа показывает это в действии в упрощенной форме (без массивов) с вашим входным файлом:

#include <stdio.h>

int main (void) {
    FILE *data;
    char room[2], paintcode[2], ceilingcode[2];
    int house, length, width;
    double cost, setupcost;

    data = fopen("quotes.data","r");
    if (data == NULL) {
        printf("Error: file can't be opened.\n");
    } else {
        while (fscanf (data, "%4d,%[A-Z],%3d,%3d,%[prb],%[yn],%lf,%lf\n",
            &house, room, &length, &width, paintcode, ceilingcode, &cost,
            &setupcost) == 8)
        {
            printf ("%d,%c,%d,%d,%c,%c,%.2lf,%.2lf\n",
                house, *room, length, width, *paintcode, *ceilingcode,
                cost, setupcost);
        }
    }
    fclose(data);
    return 0;
}
1 голос
/ 10 декабря 2011

Вам нужно брать адрес (как в &house[i]) только когда вы передаете аргументы fscanf.Целочисленные и односимвольные аргументы fprintf передаются по значению:

printf("%d,%c,%d,%d,%c,%c,%.2lf,%.2lf\n", house[i], room[i], length[i], width[i], paintcode[i], ceilingcode[i], cost[i], setupcost[i]);

Для вызова fscanf, с другой стороны, требуются указатели.Поскольку вы сканируете одиночные символы как символы, а не как строки, вы должны передавать адрес комнаты, код краски и т. Д.

0 голосов
/ 10 декабря 2011

Проверьте правильность возвращаемого значения scanf

RETURN VALUE
   These functions return the number of input items successfully matched and 
   assigned,  which  can  be fewer than provided for, or even zero in the event
   of an early matching failure.
...