【问题标题】:fgets does not fill the array completelyfgets 没有完全填充数组
【发布时间】:2014-10-30 12:32:39
【问题描述】:

我想读取一个文本文件并将其存储到数组data[512]

代码如下:

char filename = "send.txt";

//Open File
FILE *in_file = fopen("send.txt", "r");

if(in_file == NULL){
    printf("Error : couldn't oepn file");
}

char data[512];
while(fgets(data, sizeof(data), in_file) != NULL){
    printf("read size: %d \n", strlen(data));
    ...    
}

为什么strlen(data) 每次都返回不同的值?为什么data 没有填满?

编辑

在 while 循环中使用 fread() 时:

printf("Start Reading \n" );
memset(&data[0], 0, sizeof(data));
size_t numRead = fread(data,1,sizeof(data),in_file);
printf("numRead: %d \n", numRead );
if(numRead == NULL)
{
    printf(" fread() failed\n");
    return 1;
}              
printf("data size: %d \n", strlen(data));

数据大小(最后一行)不正确!

示例文本文件(除了strlen 返回 513 而不是 512 的第一个文件之外的所有文件都可以):

e Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de policys de texte。 Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la Bureautique informatique, sans que son contenu n'en soit modifié。 Il a été Popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des paragraphs du Lorem Ipsum, et, plus récemment, par sonclusion dans des applications de mise en page de texte, comme Aldus PageMaker.e Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de policys de texte。 Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la Bureautique informatique, sans que son contenu n'en soit modifié。 Il a été Popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des paragraphs du Lorem Ipsum, et, plus récemment, par sonclusion dans des applications de mise en page de texte, comme Aldus PageMaker.e Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de policys de texte。 Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la Bureautique informatique, sans que son contenu n'en soit modifié。 Il a été Popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des paragraphs du Lorem Ipsum, et, plus récemment, par sonclusion dans des applications de mise en page de texte, comme Aldus PageMaker.e Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de policys de texte。 Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la Bureautique informatique, sans que son contenu n'en soit modifié。 Il a été Popularisé dans les annees 1960 grâce à la vente de feuilles Letraset contenant des paragraphs du Lorem Ipsum, et, plus récemment, par sonclusion dans des applications de mise en page de texte, comme Aldus PageMaker。 Le Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de policys de texte。 Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la Bureautique informatique, sans que son contenu n'en soit modifié。 Il a été Popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des paragraphs du Lorem Ipsum, et, plus récemment, par sonclusion dans des applications de mise en page de texte, comme Aldus PageMaker.e Lorem Ipsum est simplement du faux texteemployé dans la composition et la mise en page avant 印象。 Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux

【问题讨论】:

  • 使用fgetc(),效率不高,但你确定会被填满。
  • 显示你的文件内容..
  • 这里可以附加文件吗?
  • @H'H 只需发布 4 行左右的文本文件以及与之关联的 strlen() 输出。

标签: c fgets


【解决方案1】:

fgets 做了什么:

C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定流中读取一行并将其存储到 str 指向的字符串中。当读取 (n-1) 个字符、读取换行符或到达文件结尾(以先到者为准)时,它会停止。

所以在你的代码中:

fgets(data, sizeof(data), in_file);

将读取最多 511 个字符,但一旦遇到新行或 EOF,它将停止读取。
如果您想读取与data 数组一样多的字符,则可以使用fgetc 逐个读取它们,或者在循环中调用fgets,每次将其余读取数据附加到data 结束。一个未经测试的示例:

size_t data_len = 0,
    total_len = 0,
    max_len = sizeof data/sizeof *data;//sizeof *data is one, unless you decide to use w_char or something
while ((fgets(data + data_len, max_len - data_len, in_file)) != NULL)
{
    data_len = strlen(data);
    if (data_len >= 511)//==511 should work, but you never know
    {
        total_len += data_len;//keep running total
        data_len = 0;
        printf("%s\n", data);
        data[0] = '\0';//make empty string
    }
}
if (data_len)
    printf("%s\nread size: %zu\n", data, total_len + data_len);

【讨论】:

    【解决方案2】:

    fgets() 将一直​​读取到换行符或文件末尾。如果您的文件必须有不同长度的换行符分隔的行。

    改用fread(),它会按照你告诉它的方式读取,除非它到达文件末尾。

    【讨论】:

      【解决方案3】:

      您必须决定这是您正在阅读的文本文件还是二进制文件。如果是文本文件,fgetsstrlen 是正确的,你是逐行读取的,所以读取的长度会有所不同。

      如果这是一个二进制文件,请使用fread,但不要在缓冲区上使用strlen。巧合的是,您的缓冲区可能有0 字节,因此strlen 会将这些字节解释为字符串结尾字符。

      【讨论】:

      • 这是一个 send.txt 文本文件。除了第一个 strlen 重新运行 513 而不是 512 的文件外,其他所有文件都可以...可能是什么原因?
      • @H'H:如果 char[512]strlen 大于 511(字符串是带有终止 \0 的字符数组),您就有调用 UB 的风险(未定义行为)
      • 没有办法避免吗??
      • @H'H:当然可以,使用 fgets 就像我在示例中所做的那样,或者使用 fread(data, sizeof *data, sizeof data/sizeof *data -1, in_file) 并确保 data[511] 始终为 \0。请注意第三个参数中的 -1:读取 最多 sizeof array -1 个字符,您 必须 为最重要的终止 \0 字符留出空间跨度>
      • @EliasVanOotegem 谢谢,现在我很好理解了。
      猜你喜欢
      • 2014-09-07
      • 2020-04-21
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 2021-02-03
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      相关资源
      最近更新 更多