【问题标题】:The strange behavior of 'read' system function“读取”系统函数的奇怪行为
【发布时间】:2015-12-08 20:28:45
【问题描述】:

我尝试编写的程序应该能够读取长度不超过 8 个字符的字符串,并检查文件中是否存在这样的字符串。我决定为此使用“读取”系统功能,但我想出了这个功能的奇怪行为。因为它是手动编写的,当到达文件末尾时它必须返回 0,但在我的情况下,当没有更多字符可以读取时,它仍然读取 '\n' 并返回 1(读取的字节数)(I'已经检查了读取字符的 ASCII 码,它实际上是 10,即 '\n')。因此,考虑到这一事实,我更改了我的代码并且它起作用了,但我仍然无法理解为什么它会以这种方式运行。这是我的函数的代码:

int is_present(int fd, char *string)
{
    int i;
    char ch, buf[9];

    if (!read(fd, &ch, 1)) //file is empty
        return 0;

    while (1) {
        i = 0;
        while (ch != '\n') {
            buf[i++] = ch;
            read(fd, &ch, 1);
        }
        buf[i] = '\0';
        if (!strncmp(string, buf, strlen(buf))) {
            close(fd);
            return 1;
        }
        if(!read(fd, &ch, 1)) //EOF reached
            break;
    }
    close(fd);
    return 0;
}

【问题讨论】:

  • 读完\n后终止了吗?
  • strncmp(string, buf, strlen(buf))strcmp(string, buf) 没有什么不同。也许你的意思是strncmp(string, buf, sizeof(buf))

标签: c


【解决方案1】:

我认为您的问题出在内部 read() 调用中。你没有检查函数的返回。

    while (ch != '\n') {
        buf[i++] = ch;
        read(fd, &ch, 1);
    }

如果文件在进入函数时恰好在EOF,并且ch等于'\n',那么它将是一个无限循环,因为read()不会修改ch的值。顺便说一句,您没有检查buf 的边界。

【讨论】:

  • 我在我的程序的以前版本中这样做了,但是,正如我所说,在文件末尾它读取了一个额外的'\n',所以,知道了,我改变了它。感谢界限
  • @VladislavKolesnikov:那么你应该发布你之前的代码,因为事实上,EOF 上的read() 什么都不做,而ch 根本没有改变。
【解决方案2】:

我假设问题是'为什么read() 会这样工作' 而不是'我的程序出了什么问题?'

这不是错误。来自manual page

成功时,返回读取的字节数(零表示文件结束),文件位置提前该数字。如果此数字小于请求的字节数,则不是错误;例如,这可能是因为现在实际可用的字节较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为 read() 被中断信号。出错时,返回-1,并正确设置errno。在这种情况下,未指定文件位置(如果有)是否更改。

如果您考虑一下read 必须以这种方式工作。如果它返回 0 表示在读取某些数据 时已到达文件末尾,那么您将不知道已读取了多少数据。因此,read 仅在由于文件结束条件而没有读取数据时才返回 0。

因此,在这种情况下,只有\n 可用,read() 将成功并返回 1。下一次读取将返回零以指示文件结束。

【讨论】:

    【解决方案3】:

    除非找到EOF,否则read() 函数会一直读取字符并将其放在缓冲区中。在这种情况下,\n 也被视为一个字符。因此它也这么写。您的代码在读取 \n 后将关闭,因为除了 EOF 之外没有其他内容。所以只有EOFread() 的分隔符,其他所有字符都被认为是正常的。干杯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多