我正在尝试从文件中读取文本以进行打印..尝试时如果我给出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个字符。 任何人都可以解释为什么会这样吗?
答案 0 :(得分:3)
这是因为read()
没有空终止输出。在将目标缓冲区用作字符串之前,需要对目标缓冲区进行空终止。
基本上将非空终止的char
数组传递给printf()
作为%s
的参数创建undefined behavior,因为可能存在超出范围的内存访问。
达到此目的的一种方法是0
- 初始化目的地。这样,在read()
读取和存储有效值之后,它将被视为空终止。像
char cbuffer[100] = {0};
可以提供帮助。
那说,改变
printf("%s",&cbuffer);
到
printf("%s",cbuffer);
因为%s
需要一个指向空终止数组char
的指针。当您将数组名称传递给函数时,它会衰减到指向第一个元素的指针,因此您应该没问题。
答案 1 :(得分:1)
您的代码有两个问题。
c中的字符串由一系列非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);
您正在将数组的地址传递给printf()
printf("%s",&cbuffer);
这是错误的,因为当printf()
找到"%s"
说明符时,它希望传递的参数是char *
指针,但是你已经传递了一个指向{{1}数组的指针1}}。当作为参数传递时,数组会自动转换为指针,一般来说,将数组转换为指针不需要特别的工作。
这是根据定义:未定义的行为,你必须注意,当你增加数组的地址时,它将增加指针的大小,而增加数组它自己 - 因为它将是类型的指针数组元素 - 按元素的大小递增。
建议:不要在一行的开头使用char
,因为某种原因,它会被称为行尾字符。它指示'\n'
刷新它正在写入的文件流,因此它应该是格式字符串中的最后一个字符。