我收到“总线错误”,试图将stdin
读入char*
变量。
我只想阅读stdin
以上的所有内容并将其放在变量中,然后继续处理变量。
我的代码如下:
char* content;
char* c;
while( scanf( "%c", c)) {
strcat( content, c);
}
fprintf( stdout, "Size: %d", strlen( content));
但不知怎的,我总是通过调用cat test.txt | myapp
返回“Bus error”,其中myapp
是上面编译的代码。
我的问题是如何在EOF之前将stdin
读成变量?正如您在代码中看到的,我只想打印来自stdin的输入大小,在这种情况下,它应该等于文件test.txt
的大小。
我认为只使用scanf
就足够了,也许可以通过缓冲方式阅读stdin
?
答案 0 :(得分:17)
首先,您传递未初始化的指针,这意味着scanf
和strcat
将写入您不拥有的内存。其次,strcat
期望两个以空字符结尾的字符串,而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);
}
编辑:正如Wolfer所提到的,输入中的NULL将导致在使用fgets时过早终止字符串。如果可用,getline是更好的选择,因为它处理内存分配并且没有NUL输入问题。
答案 1 :(得分:7)
你的问题是你从未分配过c
和content
,因此它们没有指向任何定义的位置 - 它们可能指向某些未分配的内存,或者某些内容没有存在的。然后你将数据放入其中。您需要先分配它们。 (这就是总线错误通常意味着的;你试图进行无效的内存访问。)
(或者,由于c
始终只包含一个字符,因此您可以将其声明为char c
并将&c
传递给scanf。当需要时,不需要声明一个字符串会做的。)
一旦你这样做,你就会遇到确保content
足够长以容纳所有输入的问题。您需要猜测您期望的输入量并至少分配那么长的时间(如果超过该值,则会出错),或者如果时间不够长,您需要一个策略来重新分配它。 / p>
哦,你也会遇到strcat
期望字符串而不是单个字符的问题。即使您将c
作为char*
,scanf
调用也不会使其成为字符串。单字符字符串(在内存中)是一个字符,后跟一个空字符,表示字符串的结尾。 scanf
,在扫描单个字符时,不会在其后插入空字符。结果,strcpy
不会知道字符串结尾的位置,并且会在内存中寻找空字符。
答案 2 :(得分:6)
既然你不关心实际内容,为什么还要打扰一个字符串呢?我还会使用getchar()
:
int c;
size_t s = 0;
while ((c = getchar()) != EOF)
{
s++;
}
printf("Size: %z\n", s);
此代码将正确处理文件中包含'\0'
个字符的情况。
答案 3 :(得分:1)
这里的问题是你引用了一个没有通过malloc
分配内存的指针变量,因此结果将是未定义的,并且不是唯一的,通过在未定义的指针上使用strcat
指向任何东西,你最终得到了一个总线错误!
这将是所需的固定代码....
char* content = malloc (100 * sizeof(char)); char c; if (content != NULL){ content[0] = '\0'; // Thanks David! while ((c = getchar()) != EOF) { if (strlen(content) < 100){ strcat(content, c); content[strlen(content)-1] = '\0'; } } } /* When done with the variable */ free(content);
代码强调了程序员管理内存的责任 - 对于每个malloc
,如果没有free
,则会发生内存泄漏!
修改:感谢 David Gelhar ,因为他在我的故障中指出了他的错误!我修复了上面的代码以反映修复...当然在现实生活中,也许100的固定值可以改为#define
,以便通过加倍扩展缓冲区超过realloc
的内存量并将其修剪为大小......
答案 4 :(得分:0)
假设你想获得(短于MAXL-1个字符串)字符串而不是用char处理你的文件char,我做了如下:
#include <stdio.h>
#include <string.h>
#define MAXL 256
main(){
char s[MAXL];
s[0]=0;
scanf("%s",s);
while(strlen(s)>0){
printf("Size of %s : %d\n",s,strlen(s));
s[0]=0;
scanf("%s",s);
};
}