2014-12-19 2 views
1

У меня возникла большая проблема с использованием fgetc(), и я не могу понять это ... Я пытаюсь разобрать текстовый файл, все компилируется, но при выполнении я получил бесконечный цикл xor a segfault (Code :: blocks), мой текстовый файл выглядит следующим образом: {«USD_EUR»: «0.8631364», «EUR_USD»: «1.3964719»} с изменением 16 ставок. Я пытаюсь поставить весь мой поплавок в скорости [16] ...fgetc() не умеет читать float

void read(float change[4][4], char* myFile) 
{ 

    FILE* file = NULL; 
    file = fopen(myFile, "r+"); 
    int value,i; 
    float rate[16]; 
    char* str = ""; 
    if (file != NULL) 
    { 
     do 
     { 
      value = fgetc(file); 
      printf("%c \n",value); 
      while(value > 48 && value < 57) 
      { 
       value = fgetc(file); 
       strcat(str, value); 
       //printf("%s \n", str); 
      } 
      rate[i] = atof(str); 
      i++; 
      str = ""; 
     }while(value != EOF);// 125 = } 
     change[0][1] = rate[5]; 
     change[0][2] = rate[0]; 
     change[0][3] = rate[15]; 
     change[1][0] = rate[6]; 
     change[1][1] = rate[14]; 
     change[1][2] = rate[7]; 
     change[1][3] = rate[10]; 
     change[2][0] = rate[8]; 
     change[2][1] = rate[2]; 
     change[2][2] = rate[12]; 
     change[2][3] = rate[4]; 
     change[3][0] = rate[3]; 
     change[3][1] = rate[13]; 
     change[3][2] = rate[11]; 
     change[3][3] = rate[9]; 
     fclose(file); 
    } 
    else 
    { 
     printf("Unable to read the file!\n"); 
    } 
} 

Я также попробовать с EOF, но у меня есть только символ перед числами тогда, что выходит из бывшего цикла: { «USD_EUR»: "

+1

Сколько вы понимаете C строк? Вы не можете просто 'str =" "'. – guest

+2

и пытаетесь ли вы называть 'strcat (char *, int)'? – guest

+0

в 'change', изменение положения [0] [0] пропускается. – user3629249

ответ

1

Я полагаю, что вы просто использовать fscanf.

Например

FILE *file; 
int i = 0, status; 
float value; 
float rate[16]; 

file = fopen(myFile, "r"); 
if(file == NULL){ 
    printf("Unable to read the file!\n"); 
    return ; 
} 
while((status=fscanf(file, "%f", &value))!=EOF){ 
    if(status==1){ 
     rate[i++] = value; 
     if(i==16)//full 
      break; 
    } else { 
     fgetc(file);//one character drop 
    } 
} 
fclose(file); 
+0

предлагать #define MAX_INPUTS (16) и использовать это в коде и использовать perror(), а не printf(), поскольку это выводит причину неудачи fopen, другой мудрый, отличный код – user3629249

+0

Также кажется, что это должно использовать ' двойной', чтобы думать с точки зрения точности хранения. – BLUEPIXY

1

Проблема 1:..

char* str = ""; 

str Объявляет как указатель на статическую строку Это создает буквальный "" в памяти и указывает str к нему, что не все, что вы можете безопасно изменить вы хотите что-то

char str[30] = ""; 

Проблемы 2 и 3:

strcat(str, value); 

Попытки приложить к str, который не является безопасным или вправо. Кроме того, в качестве гостевых заметок вы пытаетесь использовать strcat(char *, int), что неверно. strcat(char *, char *) является правильным. Примечание - это не означает, что вы должны strcat(str, (char *) &value); - вам нужно понять, как строки реализованы какмассивы в C, особенно в отношении нулевого завершения.

Проблема 4: комментарий

str = ""; 

знакомства user3629249 в выше. При надлежащей декларации

str[0] = '\0'; 

Было бы правильно.

Задача 5:

Опять же, с кредита user3629249,

в 'изменить', изменение позиции [0] [0] пропуску.

0

код имеет следующую последовательность:

fgetc результаты в 'U',

, которое не является значением в диапазоне 0 ...9 эксклюзивные, так проваливается, чтобы попытаться преобразовать ул, чтобы проголосовать [я]

(где «я» не был инициализирован с известным значением)

Поскольку ни цифр, сохраненные где StR точки, некоторый неизвестный сдвиг от скорости [] получает значение 0 (это неопределенное поведение)

то неизвестное значение «я» получает приращение и следующая строка: ул = «» выполняется

, который не имеет эффект на строку (если каждый литерал не находится в другом месте в секции .const)

и внешний цикл повторяется.

В конце концов, символ в диапазоне 1 ... 8 является входным

Затем, во внутреннем цикле, что первая цифра SKIPPED , а другой символ читается.

из вашего примера, что следующий символ является символом '.' Который может привести к выходу внутреннего контура

Однако строка: strcat (str, value); должен вызывать событие ошибки сегментного благодаря попытке записи в .CONST секции исполняемого

1

В дополнении к решениям, предусмотренным в других ответах, когда сталкиваются с грязной линией ввода для чтения, может быть проще использовать линию ориентированных на входных функции, предусмотренных libc (например, fgets или getline). Считывание данных одной строки в то время в буфер, часто (не всегда) дает большую гибкость при анализе данных с другими инструментами, предоставленных libc (например strtok, strsep, и т.д ..)

с другими данными, ориентированный на характер вход - лучший выбор. В вашем случае линии чередуются с многочисленными '"', ':', ' ' и ','. Это затрудняло построение строки формата fscanf для чтения обоих обменных курсов в одном вызове или с использованием любого инструмента синтаксического анализа строк, такого как strtok. Так что это был действительно жесткий вызов. Я согласен, решение BluePixyes для разбора одного float в вызове fscanf является хорошим решением. ориентированная на линию альтернатива - читать строку за раз, а затем использовать strtof для преобразования значений поплавка, найденных в строке. Единственное преимущество, которое предоставляет strtof, - это проверка ошибок при преобразовании, которая позволяет проверить хорошее преобразование поплавка.Это один из подходов для линии-ориентированного раствора:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <limits.h> 

int main() { 

    FILE* file = NULL;    /* aways initialize variables */ 
    float rate[16] = {0.0};   /* market rates 1st & 2nd  */ 
    char myFile[50] = {0};   /* input filename    */ 
    char line[128] = {0};   /* input line buffer   */ 
    char *p = NULL;     /* pointer to parse line  */ 
    char *ep = NULL;    /* pointer to parse line  */ 
    size_t idx = 0;     /* index for rate array values */ 
    size_t it = 0;     /* general index iterator  */ 

    /* prompt for filename */ 
    printf ("\n Please enter filename to read rates from: "); 
    scanf ("%[^\n]%*c", myFile); 

    /* open & validate file */ 
    file = fopen (myFile, "r"); 
    if (!file) { 
     fprintf(stderr, "error: Unable to read the file!\n"); 
     return 1; 
    } 

    /* using line-oriented input to read line, then parse */ 
    while (fgets (line, 127, file) != NULL) 
    { 
     if (idx == 16) { 
      fprintf (stderr, "warning: array full.\n"); 
      break; 
     } 

     p = line;       /* parse line for floats */ 
     while (*p) {      /* find first digit or end */ 
      while (*p && (*p < 48 || *p > 57)) p++; 
      if (!*p) break;     /* validate not null  */ 
      rate[idx++] = strtof (p, &ep); /* get float, set end-ptr */ 
      if (errno != 0 || p == ep)  /* validate conversion  */ 
       fprintf (stderr, "discarding: rate[%zd] invalid read\n", --idx); 
      p = ep;       /* set ptr to end-ptr  */ 
     } 
    } 

    fclose (file); 

    printf ("\n The exchange rates read from file:\n\n"); 
    for (it = 0; it < idx; it++) 
     printf (" rate[%2zd] = %9.7f\n", it, rate[it]); 

    printf ("\n"); 

    return 0; 
} 

ввода пробы:

$ cat dat/rates.txt 
"USD_EUR": "0.8631364", "EUR_USD": "1.3964719" 
"USD_AGT": "0.9175622", "EUR_USD": "1.0975372" 
"USD_BRZ": "0.8318743", "EUR_USD": "1.1713074" 
"USD_COL": "0.9573478", "EUR_USD": "1.0537964" 
"USD_GIA": "0.7904234", "EUR_USD": "1.5393454" 

выхода:

$ ./bin/read_xchgrates 

Please enter filename to read rates from: dat/rates.txt 

The exchange rates read from file: 

    rate[ 0] = 0.8631364 
    rate[ 1] = 1.3964719 
    rate[ 2] = 0.9175622 
    rate[ 3] = 1.0975372 
    rate[ 4] = 0.8318743 
    rate[ 5] = 1.1713074 
    rate[ 6] = 0.9573478 
    rate[ 7] = 1.0537964 
    rate[ 8] = 0.7904234 
    rate[ 9] = 1.5393454 

Примечание: проверить strtof для любого дополнительного #define может потребоваться ваш компилятор.

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