微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C 写入文件会忽略新行吗?

如何解决C 写入文件会忽略新行吗?

给定以下代码我有printf("hello\n"); 所以我期待在 hello\n 中看到 myfile。但是当我运行我的程序时,我看到 haha 这意味着 \n 被忽略了,这是为什么?

值得注意:当我用 printf("hello\n"); 替换 printf("hellos"); 时,我没有看到 s 字母也被打印出来。所以我想也许有什么东西写在上面,但问题是谁和为什么?

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <string.h>


int main() {
// creates a new file having full read/write permissions
    int fd = open("myfile",O_RDWR | O_CREAT,0666);
    write(fd,"haha\n",5);
    close(fd); // line 6
    fd = open("myfile",O_RDWR); // line 7
    close(0);
    close(1);
    dup(fd);
    dup(fd);
    if (fork() == 0) {
        char s[100];
        dup(fd);
        scanf("%s",s);
        printf("hello\n");
        write(2,s,strlen(s)); // line 18
        return 0; // line 19
    }
    wait(NULL);
    printf("Father finished\n");
    close(fd);
    return 0;
}

运行后的myfile内容

haha
helloFather finished (new line after this)

解决方法

首先,行为是未定义的。您开始使用 stdout 引用与 stdin 相同的文件描述符,而无需在执行此操作之前关闭或刷新 stdin。让我们尝试从 POSIX 2.5.1 Interaction of File Descriptors and Standard I/O Streams 中提取重要内容:

[...] 如果使用了两个或多个句柄,并且其中任何一个是流,应用程序应确保它们的动作按如下所述进行协调。如果不这样做,结果是不确定的

[...]

为了使句柄成为活动句柄,应用程序应确保在上次使用句柄(当前活动句柄)和第一次使用第二个句柄(未来活动句柄)之间执行以下操作。 [...]

[...]

对于第一个句柄,适用以下第一个适用条件。 [...]

  • [...]

  • 如果流以允许读取的模式打开,并且底层打开的文件描述指的是能够查找的设备,则应用程序要么执行 fflush(),要么关闭流。

您的代码可以:

    scanf("%s",s); // associates stdin with fd
    // Ups - no flush(stdin) nor fclose(stdin)
    printf("hello\n");  // associates stdout with fd - undefined behavior

您看到的结果来自 scanf 调用 ungetc,它增加文件位置,但一旦流被刷新,也会“记住”取消增加文件位置。因为在child终止时flush,文件位置递减,parent覆盖child的最后一个字符。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。