fgetc()无法读取浮点数

时间:2014-12-19 18:55:27

标签: c arrays parsing fgetc

我使用fgetc()遇到了一个大问题,我无法弄清楚...我尝试解析一个文本文件,一切都编译但在执行时我得到了一个无限循环x或一个段错误(Code :: blocks ),我的文本文件是这样的:{“USD_EUR”:“0.8631364”,“EUR_USD”:“1.3964719”},16个汇率变化。我试着把我所有的浮动放在率[16] ......

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,但我只有数字之前的字符,然后退出循环ex:{“USD_EUR”:“

4 个答案:

答案 0 :(得分: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中如何实现为char数组,特别是关于零终止。

问题4:

str = "";

请参阅上面的user3629249评论。给出适当的声明,

str[0] = '\0';

是对的。

问题5:

再次,归功于user3629249,

  

在'更改'中,正在跳过位置更改[0] [0]。

答案 1 :(得分:1)

我建议你只使用fscanf

E.g

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

答案 2 :(得分:1)

除了其他答案中提供的解决方案之外,当面对一系列凌乱的输入阅读时,使用{{1}提供的面向行的输入函数可能更容易(例如libcfgets)。通常(并非总是)将数据一次一行地读取到缓冲区中,可以使用getline提供的其他工具(例如libcstrtok等)更灵活地解析数据。 ..)

对于其他数据,面向字符的输入是更好的选择。在您的情况下,这些行与许多strsep'"'':'' '进行隔行扫描。这使得构造','格式字符串以在单个调用中读取两种汇率或使用任何字符串解析工具(如fscanf)变得困难。所以这真是一个艰难的要求。我同意,BluePixyes&#39;在strtok调用中解析单个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

答案 3 :(得分:0)

代码具有以下顺序:

fgetc会产生&#39; U&#39;

这不是0 ... 9范围内的值, 所以直接尝试将str转换为rate [i]

(其中&#39; i&#39;尚未初始化为已知值)

由于没有数字保存在str点, rate []的某些未知偏移量设置为0 (这是未定义的行为)

然后是未知的价值&#39;我&#39;得到增加  和以下行:str =&#34;&#34;执行

对字符串没有影响 (除非每个文字位于.const部分的不同位置)

并重复外循环。

最后,输入1 ... 8范围内的字符

然后,在内循环中,第一个数字是SKIPPED 另读一个字符。

从您的示例中,下一个字符是&#39;。&#39; 这可能导致内循环退出

然而, 行:strcat(str,value); 应该导致seg故障事件 由于尝试写入可执行文件的.const部分