【问题标题】:How to stop reading input when a certain character is reached到达某个字符时如何停止读取输入
【发布时间】:2020-02-26 23:29:23
【问题描述】:

假设有人正在写一些文本。我的程序必须扫描该文本,然后将所有字符相互打印。但是,它应该只读取输入直到 * 出现。所以当输入是“Hello*darling”时,它应该只读取“Hello”。我在 while 循环中使用 * 作为参数,但我的程序扫描的是“Hello*”而不是“Hello”。如何摆脱 *?

#include <stdio.h>

int main()
{
    char c1;
    while (c1!='*'){
        scanf("%c", &c1);
        printf("c1: %c \n", c1);
     }
    return 0;
}

【问题讨论】:

  • OT:这里你使用的是c1 uninitializted:while (c1!='*'){
  • 您在检查是否为“”后读取了 c1 的新值。然后您继续打印。之后循环再次开始,它检查字符是否匹配。直到此刻,''面包车才被检测到。

标签: c printf scanf


【解决方案1】:

你应该看看getchar()

#include <stdio.h>

int main()
{
    int c1;
    while ((c1=getchar())!=EOF && c1!='*'){
       printf("c1: %c \n", c1);
    }
    return 0;
}

编辑:这样,没有未定义的行为,因为c1 总是被初始化(参见@Blaze 答案):)

【讨论】:

  • char c1; 应该是 int c1;while ((c1=getchar())!='*') 应该是 while ((c1=getchar())!=EOF &amp;&amp; c1!='*')
  • 还有一个错字:'EOF' 应该是EOF。 :)
  • 非常感谢!所以基本上我错过了 EOF 论点。你能解释为什么这很重要吗?我不太明白为什么要消除 *,据我所知,EOF 是“文件结尾”,所以它应该是输入的结尾吗? “while”是否告诉程序:“扫描直到到达 * 并且 * 是文件的结尾”?
  • 不,这意味着:“虽然输入尚未结束 ((c1=getchar())!=EOF),并且输入与 '*' (c1!='*') 不同,但请执行...”。第一部分只是通过尝试读取已结束的输入来避免未定义行为的安全防护。
【解决方案2】:

您可以切换scanfprintf 语句,并在循环之前放置一个初始scanf

int main()
{
    char c1 = '\0';
    do {
        printf("c1: %c \n", c1);
        if (scanf(" %c", &c1) != 1)
            return -1;
    } while (c1 != '*');
    return 0;
}

还请注意,正如您的程序当前一样,不仅打印* 存在问题,而且它是未定义的行为,因为c1c1 != '*' 的第一次运行中未初始化。

【讨论】:

  • 它应该检查scanf返回值(在两个地方)。
  • @IanAbbott 好建议。我将其添加到答案中。
  • 让不为人知的表弟do {...} while (...)参与会更优雅。
  • @alk 你是对的。我一直忘记这个循环存在。 :)
  • 在任何情况下,每次用户按下回车键时,循环都会执行并额外迭代读取通过按下回车键输入的换行符。使用scanf(" %c, ...
【解决方案3】:

使用scanf()进行完整的错误检查和记录:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(void)
{
  int result = EXIT_SUCCESS; /* Be optimistic. */

  {
    int r;

    {
      char c1 = 0;
      while (EOF != (r = fscanf(stdin, " %c", &c1)) && c1 != '*')
      {
        if (1 != r)
        {
          fputs("Invalid input. Retrying ...", stderr);
        }
        else
        {
          printf("c1: %c \n", c1);
        }
      }
    }

    {
      int errno_save = errno;

      if ((EOF == r) && ferror(stdin))
      {
        errno = errno_save;
        perror("scanf() failed");
        result = EXIT_FAILURE;
      }
    }
  }

  return result;
}

【讨论】:

    【解决方案4】:
        #include<stdio.h>
        #include<ctype.h>
        int main()
        {
            char string;
            do
            {
                printf("String is :%c\n",string);
                if(scanf("%c",&string)!=1)
                {
                    return 0;
                }
            }while(string!='*');
            return 0
    }
    

    这里:


    首先,它将获取字符串字符并将其与 * 字符进行比较,如果找不到该字符,它将打印该字符。否则它会发现它将返回 0 并且程序将被淘汰。


    【讨论】:

      【解决方案5】:

      当您想在循环开始时检查条件时使用 while 或 for,如果您想在结束时检查,请执行 ... until。如果您想在中间检查,我更喜欢无限循环(“while(TRUE)”或“for(;;)”)并在中间使用 if/break。以你的循环,那将是:

      while (TRUE){
          scanf("%c", &c1);
          if (c1=='*') {
              break;
          }
          printf("c1: %c \n", c1);
      }
      

      有些人不喜欢这样,另一种方法是把它变成一个函数,使用 return 而不是 break:

      boolean get_and_print_if_not_end() {
          scanf("%c", &c1);
          if (c1=='*') {
              return true;
          }
          printf("c1: %c \n", c1);
          return false;
      }
      

      您可以在基本的 while 循环中调用它:

      while (!get_and_print_if_not_end()) {
          // Nothing to do here.
      }
      

      【讨论】:

      • This comment 也适用于此。
      • 是的,应该。 scanf() 本身就是一个很大的话题,我只是想在这里谈谈循环条件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多