C: 使用 scanf() 输入未知大小

C: Unknow size input with scanf()

我正在尝试制作一个简单的程序,您可以在其中放入一些文本,然后它会写回您刚刚写的内容。

例如,如果我写“Hello World”,程序应该回复我“Hello World”

我认为它应该如何工作:

loop to check if the current character is '[=10=]'

if not print the current character and reallocate 1 more byte of memory

else stop the loop

所以这看起来很容易做,但我的尝试没有正常工作,例如,如果你只输入几个字符,它会毫无问题地给你回信,但字符串更长..它不是完全在工作。

我知道可以使用 fgets(),但我想了解为什么我的带有 scanf() 的版本不起作用。

(我的代码)

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int mem = 2;
    char * str = malloc(mem);

    scanf("%s", str);

    while (*str != '[=11=]') {
        printf("%c", *str);
        realloc(str, mem++);
        str++;
    }

    free(str);

    return 0;
} 

edit : 我以为我只是犯了一个小错误,但是在阅读了评论之后,我似乎在这个小程序中做错了很多事情。我将确保我更好地理解 C 的工作原理并稍后重试执行此程序。感谢您的帮助!

阅读函数的手册并搜索类似的问题是一个很好的方法,可以让事情变得更清楚,并更好地理解您面临的问题:)

试试看这个问题:Reading input of unknown length, and particularly at this answer that uses scanf: scanf answer(我没有验证它是否有效,但它教你另一种你可以使用的方法)。

你的程序可以更简单

#include <stdio.h>

int main() {

    char c;
    
    while( scanf("%c", &c) == 1 ) {
        
        printf("%c", c);
    }
    
    return 0;
}

如果您要为此使用 scanf,则不应使用 "%s"。 (你永远不应该在没有字段宽度的情况下使用 "%s",因为这可能会溢出缓冲区。使用 "%s" 并不比 gets() 更好。)如果你打算使用 "%s",你需要明白它会忽略空格。除了空白问题外,以下内容 almost 是您想要的。如果要精确处理空格,则不能使用 "%s".

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

void * xrealloc(void *buf, size_t num, size_t siz, void *endvp);

int
main(void)
{
    size_t cap = 2;
    char *end = NULL;
    char *str = xrealloc(NULL, cap, sizeof *str, &end);

    /*
     * Read 1 char at a time, discarding whitespace.  This should
     * be done with getchar().  If using scanf, a single char
     * should be read with "%c".  We use "%1s" here only
     * because the question is specifically about `%s`.
     * Note that %1s will allow scanf to write up to 2 characters into
     * *end, so we need to ensure there is space for the terminator.
     */
    while( 1 == scanf("%1s", end++) ){
        while( end > str + cap - 2 ){
            str = xrealloc(str, cap *= 2, sizeof *str, &end);
        }
    }
    fputs(str, stdout);
    free(str);

    return 0;
}

void *
xrealloc(void *buf, size_t num, size_t siz, void *endvp)
{
    char **endp = endvp;
    char *b = buf;
    ptrdiff_t offset = b && endp && *endp ? *endp - b : 0;
    b = realloc(b, num * siz);
    if( b == NULL ){
        perror("realloc");
        exit(EXIT_FAILURE);
    }
    if( endp != NULL ){
        *endp = b + offset;
    }
    return b;
}