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;
}
我正在尝试制作一个简单的程序,您可以在其中放入一些文本,然后它会写回您刚刚写的内容。
例如,如果我写“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;
}