【问题标题】:Search whitespace in string inC在字符串 inC 中搜索空格
【发布时间】:2017-07-24 12:52:53
【问题描述】:

问题是当我尝试输入带有空间编译器的字符串时,将其渲染为单独的 2 个字符串。但要求是,只要字符串中有空格,就不要将其视为 2 个字符串,而是将其视为单个字符串。只有当我的四个输入是 MAHIRL、CHITRA、DEVI 和 C 时,程序才应该打印 yes。我的代码是:

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[10],str2[10],str3[10],str4[10];
    scanf("%s",str1);
    scanf("%s",str2);
    scanf("%s",str3);
    scanf("%s",str4);
    if(strcmp(str1,"MAHIRL")==0 && strcmp(str2,"CHITRA")==0 && strcmp(str3,"DEVI")==0 && strcmp(str4,"C")==0 ){
        printf("yes");
    }
    else{
        printf("no");
    }
    return 0;
}

我尝试使用 strtok() 和 strpbrk(),但我不太确定如何在我的代码中实现它们。任何帮助或建议表示赞赏。谢谢。

【问题讨论】:

    标签: c string whitespace scanf


    【解决方案1】:

    问题是当我尝试输入带有空间编译器的字符串时,将其渲染为单独的 2 个字符串

    这不是问题,这是%s 格式说明符与scanf() 特性/行为。您无法使用它读取以空格分隔的输入。

    对于转换说明符s,第 7.21.6.2 章,C11

    s 匹配一系列非空白字符。 [...]

    因此,匹配在遇到空白字符时立即结束,此处为space

    如果您必须读取 line(即,输入由 newline 终止),请改用 fgets()

    【讨论】:

      【解决方案2】:

      %s 指令在存储字符之前将字符匹配到一个空格,因此无法以这种方式获取输入行。还有其他方法可以使用scanf() 来读取输入行,但这些方法容易出错,而且这确实不是适合这项工作的工具。

      最好使用fgets() 将一行输入提取到缓冲区,并使用sscanf() 解析缓冲区。由于这里的要求是输入四个字符串,所以使用这种方法是一个简单的问题:

      #include <stdio.h>
      #include <string.h>
      
      int main(void)
      {
          char str1[10],str2[10],str3[10],str4[10];
          char buffer[100];
      
          if (fgets(buffer, sizeof buffer, stdin) == NULL) {
              fprintf(stderr, "Error in fgets()\n");
              return 1;
          }
      
          if (sscanf(buffer, "%9s%9s%9s%9s", str1, str2, str3, str4) == 4) {
              if (strcmp(str1,"MAHIRL") == 0 &&
                  strcmp(str2,"CHITRA") == 0 &&
                  strcmp(str3,"DEVI") == 0 &&
                  strcmp(str4,"C") == 0 ){
                  printf("yes\n");
              } else {
                  printf("no\n");
              }
          } else {
              printf("Input requires 4 strings\n");
          }
      
          return 0;
      }
      

      声明了一个额外的字符数组buffer[],有足够的额外空间来容纳额外的输入;这样,如果用户输入了一些额外的字符,就不太可能干扰程序的后续行为。注意fgets()如果有错误返回一个空指针,所以这个被检查了;如果在此处遇到错误,则会打印一条错误消息并退出程序。

      然后sscanf()用于解析buffer[]。请注意,最大宽度是使用 %s 指令指定的,以避免缓冲区溢出。 fgets() 函数将换行符存储在buffer[] 中(如果有空间),但是以这种方式使用sscanf() 可以避免需要进一步处理这个换行符。

      还要注意sscanf() 返回成功分配的数量;如果此返回值不是4,则输入与预期不符,不应使用str1,...,str4 保存的值。

      更新

      再次看这个问题,我不确定我是否真的回答了它。起初我以为您想使用scanf() 读取一行输入,并从中提取字符串。但是您说:“只要字符串中有空格,就不要将其视为 2 个字符串”,即使您的示例代码中的测试输入都不包含此类空格。

      将包含空格的用户输入读入字符串的一个选项是对每个字符串单独调用fgets()。如果将结果直接存储在str1,...,str4 中,则需要删除fgets() 保留的换行符。更好的方法是将结果再次存储在buffer 中,然后使用sscanf() 提取字符串,这次包括空格。这可以使用 scanset 指令来完成:

      fgets(buffer, sizeof buffer, stdin);
      sscanf(buffer, " %9[^\n]", str1);
      

      这里的格式字符串包含一个前导空格,告诉sscanf() 跳过零个或多个前导空白字符。 %[^\n] 指令告诉sscanf() 匹配字符,包括空格,直到遇到换行符,将它们存储在str1[] 中。请注意,指定的最大宽度为 9,为 \0 终止符留出了空间。

      如果您希望能够在用户输入的同一 上输入多个字符串,每个字符串都包含空格,则需要选择一个分隔符。选择一个逗号,这可以通过:

      fgets(buffer, sizeof buffer, stdin);
      sscanf(buffer, " %9[^,], %9[^,], %9[^,], %9[^,\n]", str1, str2, str3, str4);
      

      这里和之前一样有一个前导空格,用于跳过输入中可能存在的任何杂散空白字符(例如\n 字符)。 %[^,] 指令告诉sscanf() 匹配字符直到遇到逗号,并将它们存储在适当的数组中(str1[],...,str3[])。以下, 告诉sscanf() 在下一个扫描集指令之前匹配一个逗号和零个或多个空白字符。最后一个指令是%[^,\n],告诉sscanf() 匹配字符,直到遇到逗号或换行符。

      #include <stdio.h>
      #include <string.h>
      
      int main(void)
      {
          char str1[10],str2[10],str3[10],str4[10];
          char buffer[100];
      
          if (fgets(buffer, sizeof buffer, stdin) == NULL) {
              fprintf(stderr, "Error in fgets()\n");
              return 1;
          }
      
          /* Each individual string str1,..., str4 may contain spaces */
          if (sscanf(buffer, " %9[^,], %9[^,], %9[^,], %9[^,\n]",
                     str1, str2, str3, str4) == 4) {
              if (strcmp(str1,"test 1") == 0 &&
                  strcmp(str2,"test 2") == 0 &&
                  strcmp(str3,"test 3") == 0 &&
                  strcmp(str4,"test 4") == 0 ){
                  printf("yes\n");
              } else {
                  printf("no\n");
              }
          } else {
              printf("Input requires 4 comma-separated strings\n");
          }
      
          return 0;
      }
      

      这是与这个最终程序的交互示例:

      test 1, test 2, test 3, test 4
      yes
      

      【讨论】:

      • @AbhishekThakur-- 您已经接受了我的回答,但恐怕我误解了您的问题。我已经更新了我的答案,以考虑如何读取包含空格的字符串,即使是从一行用户输入中。
      • 非常感谢。我做了一些调整,一切正常!
      【解决方案3】:

      从用户读取字符串时,使用 stdio_ext.h 中的 __fpurge(stdin) 函数。这会清除标准输入。当你输入一个字符串时,最后按回车,这也是一个字符。为了避免这种情况,我们使用 fpurge 函数。

      scanf("%s",str1);
      __fpurge(stdin);
      scanf("%s",str2);
      __fpurge(stdin);
      scanf("%s",str3);
      __fpurge(stdin);
      scanf("%s",str4);
      __fpurge(stdin);
      

      另外,如果你想从用户输入一个包含空格的字符串,使用以下:

      scanf("%[^\n]", str1);
      

      这不会忽略您在输入字符串时输入的空格。

      编辑:可以使用以下代码,而不是使用 fpurge 函数:

      while( getchar() != '\n' );
      

      【讨论】:

      • 在将%s 指令与scanf() 一起使用之前,无需清除输入流中的空白字符,因为该指令自动 会忽略前导空白字符。此外,__fpurge() 是 GNU 扩展,不是标准 C 的一部分;有更好、更便携的方法来实现这一点。
      • 是的,这个循环是朝着正确方向迈出的一步。但是缺少一些关键的东西:getchar() 可以在 I/O 错误的情况下返回EOF,或者如果文件已重定向到stdin,或者如果用户从键盘发出EOF 信号。因此,循环必须检查EOF 以避免无限循环。此外,EOF 的值可能不适合char,因此必须使用int(这是getchar() 的返回类型):int c; while ((c = getchar()) != '\n' &amp;&amp; c != EOF);
      猜你喜欢
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 2013-10-17
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 2011-03-11
      • 1970-01-01
      相关资源
      最近更新 更多