我收到"总线错误"试图读取stdin到一个char*变量.我只想阅读整个过程stdin并将其放在变量中,然后继续处理变量.
我的守则如下:
char* content;
char* c;
while( scanf( "%c", c)) {
strcat( content, c);
}
fprintf( stdout, "Size: %d", strlen( content));
Run Code Online (Sandbox Code Playgroud)
但不知怎的,我总是通过调用返回"总线错误" cat test.txt | myapp,myapp上面编译的代码在哪里.
我的问题是如何将stdinEOF 读入变量?正如您在代码中看到的,我只想打印来自stdin的输入大小,在这种情况下,它应该等于文件的大小test.txt.
我以为只是使用scanf就足够了,可能是缓冲的阅读方式stdin?
Mat*_*hen 17
首先,你传递未初始化的指针,这意味着scanf并且strcat会写出你不拥有的内存.其次,strcat需要两个以null结尾的字符串,而c只是一个字符.这将再次使其读取您不拥有的内存.您不需要scanf,因为您没有进行任何实际处理.最后,一次读取一个字符是不必要的慢.这是解决方案的开始,使用可调整大小的缓冲区作为最终字符串,并为fgets调用使用固定缓冲区
#define BUF_SIZE 1024
char buffer[BUF_SIZE];
size_t contentSize = 1; // includes NULL
/* Preallocate space. We could just allocate one char here,
but that wouldn't be efficient. */
char *content = malloc(sizeof(char) * BUF_SIZE);
if(content == NULL)
{
perror("Failed to allocate content");
exit(1);
}
content[0] = '\0'; // make null-terminated
while(fgets(buffer, BUF_SIZE, stdin))
{
char *old = content;
contentSize += strlen(buffer);
content = realloc(content, contentSize);
if(content == NULL)
{
perror("Failed to reallocate content");
free(old);
exit(2);
}
strcat(content, buffer);
}
if(ferror(stdin))
{
free(content);
perror("Error reading from stdin.");
exit(3);
}
Run Code Online (Sandbox Code Playgroud)
编辑:正如Wolfer所提到的,输入中的NULL将导致在使用fgets时提前终止字符串. 如果可用,getline是更好的选择,因为它处理内存分配并且没有NUL输入问题.
你的问题是,你从来没有分配c和content,所以他们没有指向任何地方定义-他们可能指向一些未分配的内存中,或一些不存在的.然后你将数据放入其中.您需要先分配它们.(这就是总线错误通常意味着的;你试图进行无效的内存访问.)
(或者,因为c总是只保存一个字符,所以你可以将其声明为char c并传递&c给scanf.当需要时,不需要声明一串字符.)
一旦你这样做,你将遇到确保content足够长的时间来保存所有输入的问题.您需要猜测您期望的输入量并至少分配那么长的时间(如果超过该值,则会出错),或者如果时间不够长,您需要一个策略来重新分配它.
哦,你也会遇到strcat需要字符串而不是单个字符的问题.即使你离开c的char*,则scanf调用不会使它成为一个字符串.单字符字符串(在内存中)是一个字符,后跟一个空字符,表示字符串的结尾. scanf,当扫描单个字符时,不会在其后放入空字符.因此,strcpy不会知道字符串结尾的位置,并将通过内存寻找空字符.
既然你不关心实际的内容,为什么还要打扰一个字符串呢?我也用getchar():
int c;
size_t s = 0;
while ((c = getchar()) != EOF)
{
s++;
}
printf("Size: %z\n", s);
Run Code Online (Sandbox Code Playgroud)
此代码将正确处理文件中包含'\0'字符的情况.