【问题标题】:Reading in a string with spaces in C在C中读取带有空格的字符串
【发布时间】:2016-11-11 16:00:41
【问题描述】:

我正在尝试读取可能包含也可能不包含空格的字符串。 “你好世界”。通过用户输入的数字选择菜单执行以下操作。这只是我正在尝试做的一个小副本。

#include <stdio.h>
#include <string.h>

int main(void){
  char line[3][80];

  strcpy(line[0],"default line 1\n");
  strcpy(line[1],"default line 2\n");
  strcpy(line[2],"default line 3\n");

  for(int i = 0; i < 3; i++){
    printf("%s", line[i]);
  }

  int option = 0;
  printf("would you like to replace line 1? (1 for yes)\n");
  scanf("%d",&option);
  if(option==1){
   printf("what would you like to replace the line with?\n");
   fgets(line[0],strlen(line[0]),stdin);
  }

  for(int i = 0; i < 3; i++){
    printf("%s", line[i]);
  }
}

为什么我输入 1 换行后,它会打印语句询问我想用什么替换它,然后会自动输入任何内容,然后打印第一个为空的字符串?

我也已经尝试使用sscanf("%[^\n\t]s", line[0]); 阅读该行,但没有任何运气。有什么想法吗?

【问题讨论】:

  • 我猜fgets 读取了一个 eof(文件结尾)作为流的第一个字符。
  • 我很确定它与scanf("%d", &amp;option) 有关,之前询问用户是否要替换该行但我不确定是否有办法解决这个问题。
  • 与您的问题没有直接关系,但strlen(line[0]) 应替换为80。缓冲区的大小不是它包含的字符串的长度,而是缓冲区的总长度,这里是80

标签: c fgets scanf


【解决方案1】:

因为

scanf("%d",&option);

\n 字符留在标准输入中,并在第一次调用fgets() 时使用。 这就是为什么最好完全避免在 C 中使用 scanf()

您可以使用以下方法修复它:

  scanf("%d",&option);
  getchar(); /* consume the newline */

但我建议也使用fgets() 来读取option,然后您可以使用strtol() 将其转换为整数。

请注意,此声明可能不是您想要的(这限制了您可以阅读到 line[0] 的内容)。

   fgets(line[0],strlen(line[0]),stdin);

您可能打算使用:

   fgets(line[0],sizeof line[0],stdin);

这样你就可以读取到line[0]的实际大小。

请同时阅读 C 常见问题解答条目:http://c-faq.com/stdio/scanfprobs.html

【讨论】:

  • 我确认,scanf 很糟糕,这类问题很常见。 Google scanf is evil(不是开玩笑)了解更多信息。
【解决方案2】:

使用fgets() 通常看起来比使用scanf() 更不容易出错,但是如果用户输入的字符串与指定的最大字符数一样长或更长,则任何超过并包括换行符保留在输入流中。出于这个原因,我通常编写自己的gets() 版本来从用户那里获取输入字符串,如果我想要数字输入,我使用strtol()。以下是此类函数的示例:

char * s_gets(char *st, int n)
{
    char *ret;
    int ch;

    ret = fgets(st, n, stdin);
    if (ret) {
        while (*st != '\n' && *st != '\0')
            ++st;
        if (*st)
            *st = '\0';
        else {
            while ((ch = getchar()) != '\n' && ch != EOF)
                continue;           // discard extra characters
        }
    }
    return ret;
}

应用于 OPs 问题,我可能会这样做:

#include <stdlib.h>                // for strtol()

...

char buf[80];
int option = 0;

printf("would you like to replace line 1? (1 for yes)\n");
s_gets(buf, sizeof(buf));
option = strtol(buf, NULL, 10);

if(option==1){
    printf("what would you like to replace the line with?\n");
    s_gets(line[0],sizeof(line[0]));
}

【讨论】:

    【解决方案3】:

    您的问题是 '\n' 字符被留在 stdin 并被 fgets 消耗。

    我建议您始终使用fgets 进行读取输入,所以

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        char line[3][80];
        char temp[3];
    
        strcpy(line[0],"default line 1\n");
        strcpy(line[1],"default line 2\n");
        strcpy(line[2],"default line 3\n");
    
        for(int i = 0; i < 3; i++){
            printf("%s", line[i]);
        }
    
        int option = 0;
        printf("would you like to replace line 1? (1 for yes)\n");
        fgets(temp,sizeof(temp),stdin);
        option = atoi(temp);
    
        if(option==1){
            printf("what would you like to replace the line with?\n");
            fgets(line[0],sizeof(line[0]),stdin);
        }
    
        for(int i = 0; i < 3; i++){
        printf("%s", line[i]);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多