fscanf()如何处理双精度值?

时间:2018-09-29 05:52:30

标签: c double scanf

在这个问题上,我的目标是了解在处理fscanf()类型值时double的行为。语言是C。

因此,我必须读取文件中的数字并将其存储在数组中。 该文件是这样的:

1600 1 2 3 4 5 1700 6 7 8 9 10 1800 11 12 13 14 15

我只需要这些数字:166017001800(J = 3)。 我之间有五个数字(I = 5)。

如果我尝试将这些数字作为整数获取,则以下代码有效:

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

int main() {
    char filename[100];
    int *P; 
    int J = 3;
    int I = 5;  
    P = (int*)malloc(sizeof(int) * J);

    FILE *input_file;   
    iput_file = fopen("test.txt", "r");
    if (input_file == NULL) {
        fprintf(stderr, "Sorry, no such a file...\n");
        exit(1);
    }

    for (int j = 0; j < J; j++) {
        fscanf(input_file, "%d", &P[j]);
        printf("%d ", P[j]);
        for (int skip = 0; skip < I; ++skip) {
            fscanf(input_file, "%d");
        }
    }
    return 0;
}

但是,如果我试图像这样将其命名为double,那将是行不通的:

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

int main() {
    char filename[100];
    double *P;  
    int J = 3;
    int I = 5;  
    P = (double*)malloc(sizeof(double) * J);

    FILE *input_file;   
    input_file = fopen("test.txt", "r");
    if (input_file == NULL) {
        fprintf(stderr, "Sorry, no such a file...\n");
        exit(1);
    }

    for (int j = 0; j < J; j++) {
        fscanf(input_file, "%lf", &P[j]);
        printf("%lf ", P[j]);
        for (int skip = 0; skip < I; ++skip) {
            fscanf(input_file, "%lf");
        }
    }
    return 0;
}

实际上,当我运行它时,我得到了输出1600.000000,然后程序停止了,没有任何错误,好像什么都没出错。

经过数小时的思考和测试,我提出了以下解决方案。也就是说,将不需要的值放在垃圾变量中。然后,在第二个中,我将fscanf编辑为

fscanf(input_file, "%lf", &trash);

效果很好。

那么,为什么第一个代码有效而第二个代码无效?为什么使用整数而不是使用double可以呢?这和记忆有关吗?

2 个答案:

答案 0 :(得分:2)

此:

fscanf(input_file,"%lf");

是未定义的行为,因为您有一个命令计算机写入...位置的格式字符串?您没有给它写任何地方!

仅在编译时将警告作为错误启用,而这种无效代码将永远不会编译,从而使您免受各种问题的困扰:

gcc -Wall -Wextra -Werror

或者:

clang -Weverything -Werror

答案 1 :(得分:1)

如您所实验, // Auth module auth: { plugins: [ { src: '~/plugins/auth' } ], redirect: { login: '/login', logout: '/', home: false }, strategies: { local: { endpoints: { login: { url: 'account/token', propertyName: 'result.access_token' }, logout: { url: 'account/logout' }, user: { url: 'account/self', propertyName: 'result' } } } } } 具有未定义的行为。要跳过某个值,可以将其转换为临时变量,也可以使用fscanf(input_file, "%lf");之后的fscanf指定的*的赋值抑制选项:

%

还要注意,您应该测试fscanf(input_file, "%*lf"); 的返回值以检测无效的输入并避免在这种情况下的未定义行为。 fscanf()返回成功的转换次数。