【问题标题】:Copy input from user and put it on screen复制用户的输入并将其放在屏幕上
【发布时间】:2014-07-15 16:32:32
【问题描述】:

我一直在阅读 Brian W. Kernighan 和 Dennis M. Ritchie 的 The C Programming Language,目前在字符输入和输出方面,特别是在文件复制方面。书中的例子

#include <stdio.h>

int main(void)
{
    int c;

    c = getchar();

    while (c != EOF)
    {
        putchar(c);

        c = getchar();
    }

return 0;
}

完美运行。

但我决定自己动手改写一下:

#define <stdio.h>

int main(void)
{
    int c;

    printf("Please enter a digit: ");
    c = getchar();

    while (c != EOF)
    {
        printf("The digit entered was: ");
        putchar(c);

        printf("Please enter a digit: ");
        c = getchar();
    }

return 0;
}

编译执行后,我的代码的结果是:

Please enter a digit: 9
The digit entered was: 9Please enter a digit: The digit entered was:
Please enter a digit: *cursor is here*

输入应该是:

Please enter a digit: 9
The digit entered was: 9

Please enter a digit: *the cursor should be here*

另外,我对 EOF 的理解有点问题。如果有人可以帮助我解决这些问题,那就太好了。

谢谢!

【问题讨论】:

  • EOF 有什么你不明白的地方?

标签: c compilation printf getchar putchar


【解决方案1】:

大多数“终端”不会将键盘输入发送到“一次一键”程序。相反,终端将等待输入键,然后将所有按下的键(直到该点)发送到目标程序。因此,问题代码会因输入换行符\n 以及数字而受到影响。

下面的代码会丢弃所有非数字值(但也允许 EOF 值):

#include <stdio.h>
#include <ctype.h>

int main(void)
   {
   int c;

   do {
      c=0;
      /* Get user input */
      printf("Please enter a digit: ");
      while(!isdigit(c) && EOF != c)
         c = getchar();

      /* Produce output. */
      if(c == EOF)
         printf("\n");
      else
         printf("The digit entered was: %c\n", c);
      } while (c != EOF);

   return 0;
   }

编译上面的(Linux GCC例子:gcc -Wall -o test *.c

然后执行:(Li​​nux 示例:./test

Please enter a digit: 5
The digit entered was: 5
Please enter a digit: 6
The digit entered was: 6
Please enter a digit: <CTRL-D> 

&lt;CTRL-D&gt; 通常会生成 EOF 条件。

【讨论】:

    【解决方案2】:

    因为 ENTER 值“\n”(ASCII 值 10)会被

    getchar(c); 
    

    所以它会做第二次

    printf("The digit entered was: ");
    printf("Please enter a digit: "); 
    

    【讨论】:

      【解决方案3】:

      嗯,问题在于您在将您的作品提交到控制台屏幕时提供标准输入的换行符。

      让我问你这个:

      使用您所说的完美运行的代码,您可能已经尝试了一些输入,例如 "Hello!" 假设,或者可能只是像您的示例中的 "9" 这样的单个字符。您输入了'H' 然后'e' 然后'l' ...然后'!' 然后按enter-key,或者只是'9' 然后按enter -key.

      之后,您的屏幕上出现了以下内容:

      Hello!
      Hello!
      _
      

      最后一个下划线用于指示闪烁的光标。我的问题是:为什么会在那里?为什么不是在最后一个'!'旁边?

      9 相同,这将是您屏幕上的内容:

      9
      9
      _
      

      嗯,原因如下:这是因为您的程序又打印了一个您无法直接看到的字符,即换行符'\n'。证明:如果没有打印,下划线会在'!''9' 旁边闪烁。

      当您按下 enter 键 时,除了您在该会话中输入的任何内容之外,您还可以使用换行符 '\n' 来输入标准输入。标准输入得到所有这些,getchar(); 一个一个地消耗它们。

      在你的代码中没有像你预期的那样工作,你用'9' '\n'提供标准输入,getchar();首先得到'9',然后是'\n',然后它会寻找更多,但是那里不再是了。只有到那时(当没有更多时)它才会向您要求更多。

      故事就是这样……

      为了得到你所期望的,你应该做点别的,我不会直接告诉你,这是一个很好的练习。我可以提示您,您应该在已有的循环中使用另一个while 循环,并检查'\n' 遭遇的条件。

      EOF 只是一个特殊字符,或者更确切地说是一个表示位于文件末尾的特殊情况的值。对于标准输入,我猜它可以在 Linux 上用CTRL + D 组合键发出,在 Windows 上是CTRL + Z。使用该组合,然后按回车键应该可以让您摆脱外部循环。

      【讨论】:

        【解决方案4】:

        您被输入中的尾随换行符绊倒了;当您键入9 并点击Enter 时,您的代码从中读取的输入流 将包含两个 字符的编码,9 和一个换行符 (在 ASCII 中,它将是值序列 [57,10]) 。以下是它的分解方式:

        1. 代码提示您输入数字
        2. 你输入9然后回车
        3. 输入流现在包含字符{'9', '\n'}
        4. getchar 从输入流中返回下一个可用字符,即'9'
        5. '9' 不等于 EOF,所以打印数字并提示输入下一个字符
        6. getchar 从输入流中返回下一个可用字符,即'\n'
        7. '\n' 不等于EOF,所以打印字符并提示输入下一个字符
        8. 输入流现在为空,因此 getchar 会阻塞,直到您输入其他内容。

        你可以相对容易地解决这个问题:

        #include <ctype.h>
        ...
        while (c != EOF)
        {
            printf("The digit entered was: ");
            putchar(c);
        
            printf("Please enter a digit: ");
            do
            {
              c = getchar();
            } while ( isspace( c ));
        }
        

        最后一个小do 循环将从输入流中读取字符,直到它看到不是换行符或其他空白字符的内容。您可以添加额外的检查以确保输入的字符确实是数字 [0-9]:

        while (c != EOF)
        {
            printf("The digit entered was: ");
            putchar(c);
        
            do 
            {
              printf("Please enter a digit: ");
              do
              {
                c = getchar();
              } while ( isspace( c ));
        
              if ( !isdigit( c ))
                printf( "%c is not a digit!\n" );
        
            } while ( !isdigit( c ));
        }
        

        现在,有一点需要注意;您在c 中存储的不是 9,而是字符 '9' 的编码,在ASCII 中是整数值57。如果您想将 9 存储在 c 中,则必须做一些不同的事情。

        【讨论】:

          猜你喜欢
          • 2020-11-14
          • 2020-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-19
          • 2013-04-19
          相关资源
          最近更新 更多