2015-12-08 100 views
0

我试着写的程序应该能够读取长度不超过8个字符的字符串,并检查这个字符串是否出现在文件中。我决定使用'读'系统功能,但我已经想出了这个功能的奇怪行为。由于它是手动编写的,所以在到达文件末尾时它必须返回0,但在我没有更多字符的情况下,它仍然读取'\ n'并返回1(读取的字节数)(I'已经检查了读取字符的ASCII码,它实际上是'\ n'的10)。所以考虑到这个事实,我改变了我的代码,它的工作,但我仍然不明白为什么这样的行为。这里是我的函数的代码:'读'系统函数的奇怪行为

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; 
} 
+0

读完'\ n'后它终止了吗? –

+0

'strncmp(string,buf,strlen(buf))'与'strcmp(string,buf)'没有区别。也许你的意思是'strncmp(string,buf,sizeof(buf))'? –

回答

1

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

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

如果进入功能和ch等于'\n'那么这将是一个无限循环,因为read()不会修改ch值当文件正好处于EOF。顺便说一句,你没有检查buf的界限。

+0

我在我的程序的前一个版本中是这样做的,但正如我所说的,在文件末尾,它读取了一个额外的'\ n',所以,知道它后,我改变了它。谢谢你的界限 –

+0

@VladislavKolesnikov:那么你应该发布你以前的代码,因为它是EOF中的'read()'什么都不做,而且'ch'完全没有改变。 – rodrigo

+0

哦,我发现我的错误。非常感谢你! –

0

我假设的问题是“为什么read()工作这种方式”而不是“?什么是错我的计划”

这不是一个错误。从manual page

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

如果你仔细想想read必须这样工作。如果返回0表示当某个数据已经读取了,则表示文件已达到文件结尾,但您不知道读取了多少数据。因此,read仅当由于文件结束条件而未读取数据时才返回0。

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

0

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