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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2496668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:55:01  来源:igfitidea点击:

How to read the standard input into string variable until EOF in C?

cstdin

提问by NovumCoder

I am getting "Bus Error" trying to read stdininto a char*variable. I just want to read whole stuff coming over stdinand put it first into a variable, then continue working on the variable.

我在尝试读stdinchar*变量时遇到“总线错误” 。我只想阅读整个内容stdin并将其首先放入一个变量中,然后继续处理该变量。

My Code is as follows:

我的代码如下:

char* content;
char* c;
while( scanf( "%c", c)) {
 strcat( content, c);
}

fprintf( stdout, "Size: %d", strlen( content));

But somehow I always get "Bus error" returned by calling cat test.txt | myapp, where myappis the compiled code above.

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

My question is how do i read stdinuntil EOF into a variable? As you see in the code, I just want to print the size of input coming over stdin, in this case it should be equal to the size of the file test.txt.

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

I thought just using scanfwould be enough, maybe buffered way to read stdin?

我认为只使用scanf就足够了,也许是缓冲阅读方式stdin

回答by Matthew Flaschen

First, you're passing uninitialized pointers, which means scanfand strcatwill write memory you don't own. Second, strcatexpects two null-terminated strings, while c is just a character. This will again cause it to read memory you don't own. You don't need scanf, because you're not doing any real processing. Finally, reading one character at a time is needlessly slow. Here's the beginning of a solution, using a resizable buffer for the final string, and a fixed buffer for the fgets call

首先,您传递的是未初始化的指针,这意味着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] = '
int    c;
size_t s = 0;

while ((c = getchar()) != EOF)
{
  s++;
}

printf("Size: %z\n", s);
'; // 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); }

EDIT: As Wolfer alluded to, a NULL in your input will cause the string to be terminated prematurely when using fgets. getlineis a better choice if available, since it handles memory allocation and does not have issues with NUL input.

编辑:正如 Wolfer 所提到的,在使用 fgets 时,输入中的 NULL 将导致字符串过早终止。 如果可用,getline是更好的选择,因为它处理内存分配并且没有 NUL 输入问题。

回答by Brooks Moses

Your problem is that you've never allocated cand content, so they're not pointing anywhere defined -- they're likely pointing to some unallocated memory, or something that doesn't exist at all. And then you're putting data into them. You need to allocate them first. (That's what a bus error typically means; you've tried to do a memory access that's not valid.)

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

(Alternately, since cis always holding just a single character, you can declare it as char cand pass &cto scanf. No need to declare a string of characters when one will do.)

(或者,由于c始终只包含一个字符,您可以将其声明为char c并传递&c给 scanf。无需声明一串字符。)

Once you do that, you'll run into the issue of making sure that contentis long enough to hold all the input. Either you need to have a guess of how much input you expect and allocate it at least that long (and then error out if you exceed that), or you need a strategy to reallocate it in a larger size if it's not long enough.

一旦你这样做了,你就会遇到确保content足够长的时间来保存所有输入的问题。要么您需要猜测您期望多少输入并将其分配至少那么长(如果超过该时间则出错),或者您需要一种策略,如果它不够长,则将其重新分配为更大的大小。

Oh, and you'll also run into the problem that strcatexpects a string, not a single character. Even if you leave cas a char*, the scanfcall doesn't make it a string. A single-character string is (in memory) a character followed by a null character to indicate the end of the string. scanf, when scanning for a single character, isn't going to put in the null character after it. As a result, strcpyisn't going to know where the end of the string is, and will go wandering off through memory looking for the null character.

哦,您还会遇到strcat需要字符串而不是单个字符的问题。即使您c以 achar*的身份离开,该scanf调用也不会使其成为字符串。单字符字符串是(在内存中)一个字符后跟一个空字符以指示字符串的结尾。 scanf, 扫描单个字符时,不会在其后放入空字符。结果,strcpy不会知道字符串的结尾在哪里,并且会在内存中徘徊寻找空字符。

回答by Carl Norum

Since you don't care about the actual content, why bother building a string? I'd also use getchar():

既然你不关心实际的内容,为什么还要构建一个字符串呢?我也会使用getchar()

char* content = malloc (100 * sizeof(char));
char c;
if (content != NULL){
   content[0] = '
#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);
  };
}
'; // Thanks David! while ((c = getchar()) != EOF) { if (strlen(content) < 100){ strcat(content, c); content[strlen(content)-1] = '##代码##'; } } } /* When done with the variable */ free(content);

This code will correctly handle cases where your file has '\0'characters in it.

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

回答by t0mm13b

The problem here is that you are referencing a pointer variable that no memory allocated via malloc, hence the results would be undefined, and not alone that, by using strcaton a undefined pointer that could be pointing to anything, you ended up with a bus error!

这里的问题是您正在引用一个没有通过 分配内存的指针变量malloc,因此结果将是未定义的,而且不仅如此,通过使用strcat可能指向任何内容的未定义指针,您最终会遇到总线错误!

This would be the fixed code required....

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

##代码##

The code highlights the programmer's responsibility to manage the memory - for every mallocthere's a freeif not, you have a memory leak!

该代码突出了程序员的责任来管理内存-每一个malloc有一个free,如果不是,你有内存泄漏!

Edit:Thanks to David Gelharfor his point-out at my glitch! I have fixed up the code above to reflect the fixes...of course in a real-life situation, perhaps the fixed value of 100 could be changed to perhaps a #defineto make it easy to expand the buffer by doubling over the amount of memory via reallocand trim it to size...

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

回答by user3715859

Assuming that you want to get (shorter than MAXL-1 chars) strings and not to process your file char by char, I did as follows:

假设您想获取(短于 MAXL-1 个字符)字符串而不是按字符处理您的文件字符,我执行以下操作:

##代码##