我正在尝试将stdin中的多个字符串存储到一个临时变量中。
每个字符串将在换行符后输入。
这是我的尝试
#include <stdio.h>
int main() {
for (int i=0; i<10; i++) {
char string;
scanf("%s\n", &string);
printf("%d\n", i);
}
}
for循环未按预期运行,它仅循环两次,似乎scanf正在干扰循环。
stdin:
test
test
标准输出:
7631717
是否有一种方法可以将stdin中的输入/每一行动态地存储到char
变量中,而没有固定的大小/长度?
答案 0 :(得分:3)
不限于读取字符串的给定大小,可以使用修饰符'm':
char * p;
if (scanf("%ms", &p) == 1) {
...use p;
free(p); /* when stop to be usefull
}
来自 scanf
的男人:
可选的“ m”字符。这与字符串转换(%s,%c,%[)和 使调用者无需分配相应的缓冲区来保存 输入:相反,scanf()分配了足够大小的缓冲区,并分配了 此缓冲区的地址到对应的指针参数,该参数应该是 指向char *变量的指针(此变量不需要在初始化之前 电话)。调用者随后应在不再使用该缓冲区时将其释放(3)
以前的方法允许将一个“单词”涂成红色,以读取全行开头的空格(“,”,换行符,制表符...):
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * p;
if (scanf(" %m[^\n]", &p) == 1) {
printf("'%s'\n", p);
free(p);
}
else
puts("error (EOF...)");
return 0;
}
编译和执行:
/tmp % gcc -Wall c.c
/tmp % ./a.out
aze qsd
'aze qsd'
/tmp % ./a.out < /dev/null
error (EOF...)
/tmp %
如果您没有该修饰符(不是posix ...),则可以按原样阅读整行:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * p = malloc(1);
size_t len = 0;
int c;
while (((c = getchar()) != '\n') && (c != EOF)) {
p = realloc(p, len+1);
if (p == NULL) {
puts("not enough memory");
return -1;
}
p[len++] = c;
}
p[len] = 0;
printf("'%s'\n", p);
free(p);
return 0;
}
编译和执行:
/tmp % gcc -Wall c.c
/tmp % ./a.out
aze qsd
' aze qsd'
/tmp % ./a.out < /dev/null
''
/tmp %
答案 1 :(得分:2)
char string;
不是字符串而是单个字符。输入至少一个字符后,将格式为%s
的字符串读入单个字符是未定义的行为。这是因为字符串终止字符也将被追加。
写...
char string[100];
scanf("%99s", string);
一切都会好起来的。
顺便说一句:如果您打算完整地阅读(包括开头,中间和结尾的空白),请考虑使用fgets
而不是scanf
。
答案 2 :(得分:1)
有没有办法将输入/每行从stdin动态存储到char变量中,而没有固定的大小/长度?
如果愿意使用POSIX路由,请使用getline()
“动态存储stdin的输入/每一行”。
如果需要,放弃潜在的尾随换行符
char *line = NULL;
size_t len = 0;
ssize_t nread;
while ((nread = getline(&line, &len, stdin)) != -1) {
if (nread > 0 && line[nread-1] == '\n') line[--nread] = 0;
printf("Retrieved line of length %zu: <%s>\n", nread, line);
}
free(line);
我怀疑nread > 0 && line[nread-1] == '\n'
可以简化为line[nread-1] == '\n'
,因为我看不到nread
返回0的情况。