如何将标准输入读入字符串变量直到C中的EOF?

我得到“Bus Error”试图将stdin读入char*变量。 我只想阅读stdin所有内容并将其放入变量中,然后继续处理变量。

我的守则如下:

 char* content; char* c; while( scanf( "%c", c)) { strcat( content, c); } fprintf( stdout, "Size: %d", strlen( content)); 

但不知何故,我总是通过调用cat test.txt | myapp返回“总线错误” cat test.txt | myapp ,其中myapp是上面编译的代码。

我的问题是我如何读取stdin直到EOF变成变量? 正如您在代码中看到的,我只想打印来自stdin的输入大小,在这种情况下,它应该等于文件test.txt的大小。

我以为只使用scanf就足够了,也许是缓冲的方式来读取stdin

首先,你传递未初始化的指针,这意味着scanfstrcat将写入你不拥有的内存。 其次, strcat需要两个以null结尾的字符串,而c只是一个字符。 这将再次使其读取您不拥有的内存。 您不需要scanf,因为您没有进行任何实际处理。 最后,一次读取一个字符是不必要的慢。 这是解决方案的开始,使用可resize的缓冲区作为最终字符串,并为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输入问题。

你的问题是你从来没有分配过ccontent ,所以他们没有指向任何定义的东西 – 他们可能指向一些未分配的内存,或根本不存在的东西。 然后你将数据放入其中。 您需要先分配它们。 (这就是总线错误通常意味着的;你试图进行无效的内存访问。)

(或者,因为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); 

此代码将正确处理文件中包含'\0'字符的情况。

这里的问题是你正在引用一个没有通过malloc分配内存的指针变量,因此结果将是未定义的,并且不是唯一的,通过在可能指向任何东西的未定义指针上使用strcat ,你最终得到了一个总线错误!

这将是所需的固定代码….

 char * content = malloc(100 * sizeof(char));
 char c;
 if(content!= NULL){
    content [0] ='\ 0';  //谢谢大卫!
    while((c = getchar())!= EOF)
    {
        if(strlen(content)<100){
            strcat(内容,c);
            content [strlen(content)-1] ='\ 0';
        }
    }
 }
 / *完成变量* /
游离(内容);

代码强调了程序员管理内存的责任 - 对于每个malloc都有free如果没有,你有内存泄漏!

编辑:感谢David Gelhar在我的故障中指出了他的意思! 我已修复上面的代码以反映修复...当然在现实生活中,也许100的固定值可能会改为#define ,以便通过加倍量来扩展缓冲区内存通过realloc并修剪它的大小......

假设你想得到(短于MAXL-1个字符串)字符串而不是用char处理你的文件char,我做了如下:

 #include  #include  #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); }; }