【问题标题】:printf overwriting, strcat appends only first line of the fileprintf 覆盖,strcat 仅附加文件的第一行
【发布时间】:2019-06-02 17:15:51
【问题描述】:

我正在完成一项简单的任务:从 文件 中一次读取一行,打印该行并将所有内容附加到一个 char 数组中。这一切都始于我项目中的Segmentation fault (core dumped),然后我继续隔离我的代码,直到我达到这个:

#include <stdio.h>
#include <string.h>
int main(void)
{
    FILE *fp;
    fp = fopen("read.txt","r");
    char buffer[255];
    char longBuff[1024] = "";
    while(fgets(buffer, 255, fp)) {
        printf("%s\n",buffer);
        strcat(longBuff, buffer);
    }
    fclose(fp);
    printf("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWTF%s\n", longBuff);
}

read.txt 文件:

short
this is Longer
+++++
sad

还有输出:

sad++is Longer
sad++is LongerWWWWWWWWWWWWWWWWWWWTFshort

当我满怀信心地期待时:

short
this is Longer
+++++
sad
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWTFshortthis is Longer+++++sad

我遇到过多个类似的问题,大多数答案都指向carriage return,但我仍然不明白这种行为以及它的原因是什么。

【问题讨论】:

  • 我怀疑您使用的是 Unix/Linux,但打开了一个带有 Windows 行结尾的文本文件。尝试十六进制转储文本文件并查找 \r\n (0xD 0xA)。输出回车会将光标重置到行首。要解决此问题,您可以让您的程序删除回车,或修复文本文件以不包含它们
  • while (fgets(...))下方添加buffer[strcspn (buffer, "\r\n")] = 0;
  • 有趣的是,我在 Linux 上用buffer[strcspn (buffer, "\r\n")] = 0; 运行了你的代码,你的输入文件以 CRLF 结尾,我得到了你预期的输出。你有没有十六进制转储你的文件?你确定不是 UTF-16?
  • 这是一个猜测,但您是在 VS-Code 中创建原始文件,还是从 Internet 下载文件?使用hexdump -Cv read.txt 进行检查。这样您就可以查看文件中的字节。您还可以使用 Linux file 实用程序来确定文件是什么,例如file read.txt。您的文件也可能有一个搞砸的 BOM(字节顺序标记)。你不会知道,直到你看。此外,为了消除一些谜团,buffer[strcspn (buffer, "\r\n")] = 0; 所做的只是从buffer 中修剪行尾。 (strcspn 返回buffer NOT "\r\n" 中的初始字符数)
  • 所有现代编辑器中都有选项允许使用LF(换行Unix行结尾)、CRLF(回车换行DOS行结尾)和是的@987654341保存@(回车 Mac Pre-OSX 行结尾)。不知何故,你告诉gedit 做后者(它应该默认为LF 行尾)。当您说“从头开始创建”时,如果您刚刚打开 gedit 并键入了文件,保存后仍然以 CR 行结尾结束,您需要检查您的设置,以免再次发生这种情况。祝你编码顺利。

标签: c file printf stdout


【解决方案1】:

该文本文件可能源自以"\r\n" 行结尾@M.M 的平台。

如果出现"\r",一个简单的解决方案会利用它,它是行尾的压倒性部分,很容易被砍掉。 strcspn()

我现在看到 @David C. Rankin 提出了这个建议。

while(fgets(buffer, sizeof buffer, fp)) {
  // Find length of string not made up of '\n', '\r', '\0'
  // This nicely lops off the line ending, be it "\n", "\r\n" or missing.
  buffer[strcspn(buffer, "\n\r")] = '\0';
  printf("<%s>\n",buffer);
}

不幸的是,当文本文件行尾仅使用 "\r" 时,fgets()(在需要 "\n" 的系统上)将看不到任何行尾。需要一种新的方法。

【讨论】:

    【解决方案2】:

    当我使用 Linux 时,问题出在输入文件上。在运行file read 之后,我得到了read: ASCII text, with CR line terminators,并且 CR LT 导致了该阶段的覆盖行为。使用相同的文本创建了一个新的输入文件newFile: ASCII text,并且输出符合预期。

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 2020-04-28
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多