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

Nov*_*der 8 c stdin

我收到"总线错误"试图读取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输入问题.


Bro*_*ses 7

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

(或者,因为c总是只保存一个字符,所以你可以将其声明为char c并传递&c给scanf.当需要时,不需要声明一串字符.)

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

哦,你也会遇到strcat需要字符串而不是单个字符的问题.即使你离开c的char*,则scanf调用不会使它成为一个字符串.单字符字符串(在内存中)是一个字符,后跟一个空字符,表示字符串的结尾. scanf,当扫描单个字符时,不会在其后放入空字符.因此,strcpy不会知道字符串结尾的位置,并将通过内存寻找空字符.

  • 它们不是NULL,它们有未定义的值. (5认同)

Car*_*rum 7

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

int    c;
size_t s = 0;

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

printf("Size: %z\n", s);
Run Code Online (Sandbox Code Playgroud)

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

  • `c`应声明为`int`,以包括`char`加上`EOF`的范围. (3认同)