【问题标题】:fscanf fails on last row of input (negative values only?)fscanf 在输入的最后一行失败(仅负值?)
【发布时间】:2021-09-04 16:50:46
【问题描述】:

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

文件的最后一行有时会出现在结果中,有时不会。 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
-7.5953,-7.2105
**没有最后一行**

我使用的主要功能:

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

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

谢谢!

【问题讨论】:

  • 使用fgets 读取行,然后使用strtok / strtod 解析。

标签: c input


【解决方案1】:

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

格式良好的文件:

-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 将处理第一个文件,但不会处理第二个文件。


另外,在fscanf 中,"%f" 用于float,但[如果] 你有double,你需要"%lf"

事实上,您正在扫描到coordinate,这是一个float,但您的向量是double,所以您[可能]在一开始就失去了精度。最好直接扫描到向量元素中。


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

如果你每行有一个固定个数字,你可以这样做:

int count;
double vec[1000];

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

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


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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多