【问题标题】:Loop through user input with getchar使用 getchar 循环访问用户输入
【发布时间】:2015-06-19 13:33:38
【问题描述】:

我编写了一个小脚本,使用 C 中的 getchar() 函数从用户输入中检测完整值。由于 getchar() 仅返回我尝试循环遍历的第一个字符...我尝试过的代码我自己是:

#include <stdio.h>

int main()
{
    char a = getchar();
    int b = strlen(a);

    for(i=0; i<b; i++) {
        printf("%c", a[i]);
    }
    return 0;
}

但是这段代码并没有给我用户输入的全部价值。

【问题讨论】:

  • 首先阅读strlen()... 它接受char[] 类型的输入而不是char
  • 你在 char 上做 strlen()。这会导致未定义的行为,你可以得到任何东西作为返回值......你应该改变你的循环逻辑!

标签: c user-interface loops getchar


【解决方案1】:

你可以这样循环部分

int c;
while((c = getchar()) != '\n' && c != EOF)
{
    printf("%c", c);
}

【讨论】:

  • 一种老式的方法:while((c=getchar())!=EOF &amp;&amp; c!='\n') putchar(c);。顺便说一句,您可能指的是&amp;&amp; 而不是||
  • 这段代码对我不起作用..你能给我一个工作演示吗
  • @mysqllover 请提供包含您完整代码的链接
【解决方案2】:

getchar() 返回int,而不是char。而且每次迭代只返回一个字符。但是一旦输入终止,它就会返回EOF

您不检查 EOF(实际上,当 getchar()char 时,您无法立即检测到)。

a 是char,不是数组,也不是字符串,您不能将strlen() 应用于它。

strlen() 返回size_t,它是无符号的。

启用大多数警告,您的编译器想帮助您。

旁注:char 可以签名或未签名。

读一本 C 书!您的代码很糟糕,并且您混淆了多个基本概念。 - 无意冒犯!

首先,试试这个:

#include <stdio.h>

int main(void)
{
    int ch;

    while ( 1 ) {

        ch = getchar();
    x:  if ( ch == EOF )     // done if input terminated
            break;

        printf("%c", ch);    // %c takes an int-argument!
    }

    return 0;
}

如果你也想在其他字符串上终止,#include &lt;string.h&gt; 并将行 x: 替换为:

if ( ch == EOF || strchr("\n\r\33", ch) )

如果ch 是字符串文字中列出的字符之一(此处为:换行符、返回、ESCape),这将终止。但是,它也将匹配终止'\0'(不确定您是否可以输入)。

在优秀的 C 书籍中展示了将其存储到数组中(至少您将学会如何自己做)。

【讨论】:

    【解决方案3】:
    • 第 1 点:在您的代码中,a 不是数组类型。你不能在上面使用数组下标运算符。

    • 第 2 点:在您的代码中,strlen(a); 是错误的。 strlen() 计算 string 的长度,即以 null 结尾的 char 数组。您需要将指向字符串的指针传递给strlen()

    • 第 3 点: getchar() 不会自行循环。您需要将getchar() 放入循环中以继续读取输入。

    • 第 4 点: getchar() 重新运行 int。您应该相应地更改变量类型。

    • 第五点:推荐main()的签名是int main(void)

    记住以上几点,我们可以编写一个伪代码,看起来像

    #include <stdio.h>
    #define MAX 10
    
    int main(void)                        // nice signature. :-)
    {
        char arr[MAX]  = {0};            //to store the input
        int ret = 0;
    
        for(int i=0; i<MAX; i++)      //don't want to overrrun array
        {
          if ( (ret = getchar())!= EOF)  //yes, getchar() returns int
          {
                arr[i] = ret;
                printf("%c", arr[i]);
          }
          else
               ;//error handling
        }
        return 0;
    }
    

    看这里LIVE DEMO

    【讨论】:

      【解决方案4】:

      getchar() : 得到一个字符(一个字符)而不是你想要的字符串

      使用fgets():获取字符串或gets()(不推荐)或scanf()(不推荐)

      但首先你需要分配字符串的大小:char S[50] 或使用malloc#include&lt;stdlib.h&gt;):

      char *S;
      S=(char*)malloc(50);
      

      【讨论】:

      • 标准警告:不要将void * 转换为指针!使用幻数是完全错误的。
      • 永远不要谈论gets;它很危险且已被弃用。总是推荐至少fgets
      【解决方案5】:

      您似乎想阅读一行(您的问题提到了“完整值”,但您没有解释这是什么意思)。

      您可以简单地使用fgets 来实现此目的,但您必须提供固定大小的行缓冲区(并处理 - 或忽略 - 行大于缓冲区的情况)。所以你会编码

      char linebuf[80];
      memset (linebuf, 0, sizeof(linbuf)); // clear the buffer
      char* lp = fgets(linebuf, sizeof(linebuf), stdin);
      if (!lp) { 
        // handle end-of-file or error
      }
      else if (!strchr(lp, '\n')) {
        /// too short linebuf
      }
      

      如果您使用的是 POSIX 系统(例如 Linux 或 MacOSX),则可以使用 getline(动态分配缓冲区)。如果你想在 Linux 上使用一些行版功能,也可以考虑readline(3)

      避免使用过时的gets

      一旦您将一行读入某个缓冲区,您就可以对其进行解析(例如,使用手动解析,或sscanf - 注意有用的%n 转换规范,并测试sscanf 或@ 的结果计数987654325@ - 注意它可以给你结束指针 - 等等...)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-14
        • 2022-08-04
        • 1970-01-01
        • 2013-02-10
        • 2011-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多