read()从文件中返回多余的字符

时间:2016-05-28 13:23:50

标签: c string file io

我正在尝试从文件中读取文本以进行打印..尝试时如果我给出char缓冲区大小,则返回一些额外的字符..

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){

    int fd = open("text.txt",O_RDONLY);

    char cbuffer[100];
    int a =0;
    if(fd>0){
        puts("File open");
        ssize_t len = read(fd,cbuffer,sizeof(cbuffer));
        a =printf("%s",&cbuffer);
        printf("\n return data count  %d",a);
    }

    return 0;

}

如果不是

ssize_t len = read(fd,cbuffer,sizeof(cbuffer));

ssize_t len = read(fd,cbuffer,10);

完全返回10个字符。 任何人都可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:3)

这是因为read()没有空终止输出。在将目标缓冲区用作字符串之前,需要对目标缓冲区进行空终止。

基本上将非空终止的char数组传递给printf()作为%s的参数创建undefined behavior,因为可能存在超出范围的内存访问。

达到此目的的一种方法是0 - 初始化目的地。这样,在read()读取和存储有效值之后,它将被视为空终止。像

这样的东西
  char cbuffer[100] = {0};

可以提供帮助。

那说,改变

 printf("%s",&cbuffer);

printf("%s",cbuffer);

因为%s需要一个指向空终止数组char的指针。当您将数组名称传递给函数时,它会衰减到指向第一个元素的指针,因此您应该没问题。

答案 1 :(得分:1)

您的代码有两个问题。

  1. 中的字符串由一系列非null字节后跟一个null字节组成。 null字节表示字符串中不再有字节。 null字节将存储在文件中并不是不可能但不常见,此外,如果文件是文本文件,它几乎可以肯定它不会包含必要的null }字节。如果您只想显示文件的内容,则可以使用类似read()的函数输出数据,而不关心null字节,而是将可用字节数作为参数,例如

    ssize_t length = read(fd, cbuffer, sizeof(cbuffer);
    if (length == -1)
        return do_something_an_error_occurred();
    else
        write(STDOU_FILENO, cbuffer, length);
    
  2. 您正在将数组的地址传递给printf()

    printf("%s",&cbuffer);
    

    这是错误的,因为当printf()找到"%s"说明符时,它希望传递的参数是char *指针,但是你已经传递了一个指向{{1}数组的指针1}}。当作为参数传递时,数组会自动转换为指针,一般来说,将数组转换为指针不需要特别的工作。

    这是根据定义:未定义的行为,你必须注意,当你增加数组的地址时,它将增加指针的大小,而增加数组它自己 - 因为它将是类型的指针数组元素 - 按元素的大小递增。

  3. 建议:不要在一行的开头使用char,因为某种原因,它会被称为行尾字符。它指示'\n'刷新它正在写入的文件流,因此它应该是格式字符串中的最后一个字符。