【问题标题】:Use fgetc to get the number of rows in C使用 fgetc 获取 C 中的行数
【发布时间】:2021-05-12 06:56:25
【问题描述】:

我的数据如下:

0.05 1.3
0.09 1.8
0.12 1.9

我创建了两个变量 x 和 y 来分别存储它们。

    FILE *fp_data;
    double *x;
    double *y;
    int data_size;
    char ch;
    int i;

    fp_data = fopen(path, "r");
    while( ( ch = fgetc(fp_data)) != EOF) if(ch=='\n') ++data_size;

    if (!fp_data)
    {
        printf("Data file cannot open...\n");
        exit(1);
    }
    else
    {   
        x = (double*)malloc(data_size * sizeof(double));
        y = (double*)malloc(data_size * sizeof(double));
        
        printf("\n%d\n\n", data_size);
        
        for (i = 0; i < data_size; ++i)
        {
            fscanf(fp_data, "%lf %lf\n", &x[i], &y[i]);

        }
        
        fclose(fp_data);
        
        for (i = 0; i < data_size; ++i)
        {
            printf("%d- %f %f\n", i, x[i], y[i]);
            
        }
    }

我注意到我的结果是错误的,例如:

0.000000 0.000000
0.000000 0.000000
0.000000 0.000000

但是,如果我删除while( (ch = fgetc(fp_data)) != EOF ) if(ch=='\n') ++data_size; 代码并手动设置data_size,那么一切都很好。

有谁知道fgetc代码有什么问题吗?

【问题讨论】:

  • 我想你应该 rewind() 文件。 linux.die.net/man/3/rewind
  • data_size 未正确初始化。您应该使用 -Wall 进行编译并修复所有警告。
  • data_size 未初始化。此外,ch 的类型必须是 int,而不是 char
  • "Data file cannot open...\n" 是无用错误消息的典型示例。使用if( (fp_data = fopen(path, "r")) == NULL ){ perror(path); ...

标签: c string fgets


【解决方案1】:

您的代码中有一些错误。

首先,您永远不会初始化data_size 变量;这是未定义的行为:尽管一些编译器/平台可能将此类“自动”变量的初始值设置为零,但您应该从不 依靠它。解决方案:显式在声明时初始化为零:int data_size = 0;

其次,您应该检查在fp_data 文件指针上的任何进一步操作之前 是否打开文件失败(尽管我找不到显式提及它在 C 标准中,使用 NULL 指针调用 fgetc() 可能会导致未定义的行为)。通过将该检查放在适当的位置,您可以省去else 条件块(因为如果fopen() 调用失败,您的程序将调用exit(1))。

第三,您需要在while ((ch = fgetc(fp_data)) != EOF) ... 循环之后将文件指针重置为流的开头!否则,您将尝试从已经位于EOF 的文件中读取数据。您可以使用rewind() function 来执行此操作。

第四:注意fgetc function返回的是int,而不是char;使用char 类型可能导致检测EOF 信号时出现问题

其他要点:

  1. 使用后不要忘记free分配的内存。
  2. Do I cast the result of malloc?
  3. 为了稳健性,对data_size(和i)使用size_t 类型。

这是您的代码版本,上面有地址(并已注释):

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

char path[] = "test.txt"; // Or whatever!

int main()
{
    FILE* fp_data;
    double* x;
    double* y;
    size_t data_size = 0; // MUST initialize to zero
    int ch; // Note: "fgetc" return an "int" type, not "char"
    size_t i;

    fp_data = fopen(path, "r");
    if (!fp_data) {
        printf("Data file cannot open...\n");
        exit(1);
    }

    while ((ch = fgetc(fp_data)) != EOF) if (ch == '\n') ++data_size;

    rewind(fp_data); // MUST rewind the file to the beginning, before reading the data!

    x = malloc(data_size * sizeof(double));
    y = malloc(data_size * sizeof(double));
    printf("\n%zu\n\n", data_size);
    for (i = 0; i < data_size; ++i) { // Use the "%zu" format for "Size_t" types
        fscanf(fp_data, "%lf %lf\n", &x[i], &y[i]);
    }

    fclose(fp_data);

    for (i = 0; i < data_size; ++i) {
        printf("%zu- %f %f\n", i, x[i], y[i]);
    }

    free(x); // Release allocated memory after use.
    free(y);

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多