首页 > 解决方案 > fscanf 在输入的最后一行失败(仅负值?)

问题描述

我写了一个函数来解析文件输入。该文件包含一行浮点数,该函数应该将它们放入一组向量中。

文件的最后一行有时会出现在结果中,有时不会。fscanf 返回 1,最后一行的输入将失败。我添加了一个示例来重现该问题。

源代码:

typedef struct vectors { 
        double** vecs; 
        int n; /* number of vectors */
} vectors;

vectors* parseInput(char* file_name, int dim) {
    float coordinate;
    char c;
    double *vec;
    int i=0, ind=0, j=0, debug;
    FILE* input;
    vectors* datapoints;
    double** vex = (double**) calloc (1000*dim, sizeof (double*)); 
    assert(vecs != NULL);
    datapoints = (vectors*)malloc(sizeof(vectors));
    assert(datapoints != NULL);
    input = fopen(file_name, "r");
    assert(input != NULL);
 
    while (1) { /* loop until EOF */
        debug= fscanf(input, "%f%c", &coordinate, &c);
        printf("%d%s", debug, "\n");
        if(debug!=2)
        {
            printf("%s%d%s","fscanf value: ",debug,"\n"); // if in last row (that has negative values), will print 1
            printf("value: ");
            printf("%lf",coordinate);
            printf(" char: ");
            printf("%c", c);
            break;
        }
         if (j == 0)
        {
            vec = (double *)calloc(dim, sizeof(double));
            assert(vec != NULL);
        }
        if(c!='\n' && coordinate!='\n')
        {
        vec[j] = coordinate;
        j++;
        }
        if (j == dim)
        {
            print_vec(vec, dim);
            vecs[i] = vec;
            i++;
            j = 0;
        }
    }
    vecs = (double**)realloc(vecs, i*sizeof(double*));
    assert(vecs != NULL);
    datapoints->vecs = vecs;
    datapoints->n = i;
    fclose(input);
    return datapoints;
}


在输入上(作为 txt 文件)

-5.05604381
​​,11.01146785 -6.40861975,-7.96222506
5.69419195,9.60601354
6.60569313,9.39602582
-6.771797,-5.72717303
-4.49752324,8.39891449
-4.98452388,9.0760693
4.42351449,8.81860878
-7.59529807,-7.21054155
-4.19783158,8.37108438

输出将是:

-5.0560,11.0115
-6.4086,-7.9622
5.6942,9.6060
6.6057,9.3960
-6.7718,-5.7272
-4.4975,8.3989
-4.9845,9.0761
4.4235,8.8186 **
105.5953,-7
**2最后一行

我使用的主要功能:

int main(int argc, char** argv){
    int i;
    int k = atoi(argv[1]);
    int dim = get_dim_from_file(argv[3]); // works fine
    vectors* datapoints = parseInput (argv[3], dim); //the function in discussion
    double** vecs = datapoints->vecs;
    int n = datapoints->n;
    const char* goal = argv[2];
    if(!strcmp(goal, "parse"))
    {
        printf("%s%d%s","\n", datapoints->n,"\n" );
        print_matrix(datapoints->vecs, datapoints->n, dim);
    }

}

void print_matrix(double** A, int n, int k) {
    int row, col;
    for (row = 0; row < n; row++) {
        for (col = 0; col < k-1; col++) {
            if ((A[row][col] < 0) && (A[row][col] > -0.00005)) {
                A[row][col] = 0;
            }
            printf("%.4f%s", A[row][col], ",");
        }
        if ((A[row][k-1] < 0) && (A[row][k-1] > -0.00005)) {
            A[row][k-1] = 0;
        }
        printf("%.4f%s", A[row][k-1], " \n");
    }
}

如果有人知道如何解决这个问题,那就太好了!

谢谢!

标签: cinput

解决方案


某些文本文件的最后一行末尾没有换行符。

格式良好的文件:

-5.05604381,11.01146785\n
-6.40861975,-7.96222506\n
...
-4.19783158,8.37108438\n

一个格式不太好的 [但仍然有效的] 文件:

-5.05604381,11.01146785\n
-6.40861975,-7.96222506\n
...
-4.19783158,8.37108438

fscanf将处理第一个文件,但处理第二个文件。


此外, in fscanf,"%f"代表 a float,但是 [如果] 你有 a double,你想要"%lf".

实际上,您正在扫描coordinate的是 afloat但您的向量是double,因此您[可能]从一开始就失去了精度。最好直接扫描到向量元素中。


注意:为简洁起见,我省略了动态数组分配。

如果每行有固定数量的数字,您可以执行以下操作:

int count;
double vec[1000];

while (1) {
    if (fscanf(input,"%lf,%lf",&vec[count + 0],&vec[count + 1]) != 2)
        break;
    count += 2;
}

这适用于任何一种情况,并且更常见/惯用。


如果每行有一个变量计数,最好使用fgetsand strtod

就个人而言,我更喜欢这个,因为它可以提供更好的错误检测/控制。

int count;
double vec[1000];
char buf[100];

while (1) {
    char *cp = fgets(buf,sizeof(buf),input);
    if (cp == NULL)
        break;

    while (1) {
        vec[count++] = strtod(cp,&cp);

        // no newline
        if (*cp == 0)
            break;

        // has a newline
        if (*cp == '\n')
            break;

        // syntax error
        if (*cp++ != ',')
            break;
    }
}

推荐阅读