【问题标题】:fgetc() can't read floatfgetc() 无法读取浮点数
【发布时间】:2023-03-13 14:05:01
【问题描述】:

我在使用 fgetc() 时遇到了一个大问题,我无法弄清楚...我尝试解析一个文本文件,一切都编译但在执行时我得到了一个无限循环 xor 一个段错误(代码::块),我的文本文件是这样的: {"USD_EUR": "0.8631364", "EUR_USD": "1.3964719"} 有 16 种利率变化。我试着把我所有的浮动都放在 rate[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,但我只有数字前的字符然后退出循环例如:{“USD_EUR”:“

【问题讨论】:

  • 你对C字符串了解多少?你不能只是str = ""
  • 你想打电话给strcat(char *, int)吗?
  • 在'change'中,位置变化[0][0]被跳过。
  • 行:while(value > 48 && value
  • while (value &gt; 48 &amp;&amp; value &lt; 57) 将跳过小数分隔符。

标签: c arrays parsing fgetc


【解决方案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);

【讨论】:

  • suggest #define MAX_INPUTS (16) 并在代码中使用它,并使用 perror() 而不是 printf() 因为这将输出 fopen 失败的原因,否则,优秀的代码
  • also 看来这应该使用double 来考虑保留准确性。
【解决方案2】:

问题一:

char* str = "";

str 声明为指向静态字符串的指针。这会在内存中创建一个文字 "" 并将 str 指向它,这不是您可以安全更改的任何内容。你想要类似的东西

char str[30] = "";

问题 2 和 3:

strcat(str, value);

尝试附加到str,这是不安全或不正确的。此外,正如客人所说,您正在尝试strcat(char *, int),这不是正确的用法。 strcat(char *, char *) 是正确的。注意 - 这并不意味着你应该 strcat(str, (char *) &amp;value); - 你需要了解字符串是如何在 C 中实现为 char 数组的,特别是关于零终止。

问题 4:

str = "";

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

str[0] = '\0';

应该是正确的。

问题 5:

再次感谢 user3629249,

在'change'中,位置变化[0][0]被跳过。

【讨论】:

    【解决方案3】:

    除了其他答案提供的解决方案外,当面对一行乱七八糟的输入阅读时,使用libc(例如fgetsgetline)。将数据一次一行读入缓冲区,通常(并非总是)允许使用libc 提供的其他工具(例如strtokstrsep 等)更灵活地解析数据。

    对于其他数据,面向字符的输入是更好的选择。在您的情况下,这些行与许多 '"'':'' '',' 交织在一起。这使得构建fscanf 格式字符串以在单个调用中读取两种汇率或使用任何字符串解析工具(如strtok)变得困难。所以这确实是一个艰难的决定。我同意,BluePixyes 在fscanf 调用中解析单个float 的解决方案是一个很好的解决方案。 面向行的 替代方法是一次读取一行,然后使用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

    【讨论】:

      【解决方案4】:

      代码有如下顺序:

      fgetc 结果为 'U',

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

      (其中“i”尚未初始化为已知值)

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

      然后未知值“i”递增 并执行以下行:str = "" 被执行

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

      并重复外部循环。

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

      然后,在内部循环中,第一个数字被跳过 并读取另一个字符。

      从您的示例中,下一个字符是“。” 这可能会导致内部循环退出

      然而, 该行:strcat(str,value); 应该导致段错误事件 由于试图写入可执行文件的 .const 部分

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-13
        • 2020-01-24
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 2014-04-01
        相关资源
        最近更新 更多