scanf()在for循环中无法正常工作

时间:2020-07-07 08:50:08

标签: c loops for-loop input scanf

我正在尝试将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变量中,而没有固定的大小/长度?

3 个答案:

答案 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的情况。