scanf() 在 for 循环中不能正常工作

scanf() not working correctly within for loop

我正在尝试将多个字符串从标准输入存储到一个临时变量中。

每个字符串将在换行符之后输入。

这是我的尝试:

#include <stdio.h>
int main() {
    for (int i=0; i<10; i++) {
        char string;
        scanf("%s\n", &string);
        printf("%d\n", i);
    }
}

for 循环没有按预期 运行,它只循环两次,似乎 scanf 干扰了循环。

标准输入:

test
test

标准输出:

7631717

有没有一种方法可以将标准输入中的 input/each 行动态存储到 char 变量中,而无需固定 size/length?

char string; 不是字符串而是单个字符。只要输入至少一个字符,就将格式为 %s 的字符串读入单个字符是未定义的行为。这是因为字符串终止字符也会被附加。

写...

char string[100];
scanf("%99s", string);

一切都会好起来的。

顺便说一句:如果你打算阅读完整的行(包括开头、中间和结尾的空格),请考虑使用 fgets 而不是 scanf

要不限于给定大小读取字符串,您可以使用修饰符 'm' :

char * p;

if (scanf("%ms", &p) == 1) {
  ...use p;
  free(p); /* when stop to be usefull
}

来自 scanf 的人:

An optional 'm' character. This is used with string conversions (%s, %c, %[), and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead, scanf() allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to a char * variable (this variable does not need to be initialized before the call). The caller should subsequently free(3) this buffer when it is no longer required.

以前的方法允许红色 'word',以读取整行,在开头删除空格(' '、换行符、制表符 ...):

#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 % 

Is there a way to store input/each line from stdin dynamically into a char variable without a fixed size/length?

如果愿意走 POSIX 路线,请使用 getline() 来“动态存储来自标准输入的 input/each 行”。

如果需要,删除潜在的尾随换行符

       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 returns 0.

的情况