怎样在控制台里面输入密码的时候显示*

 

         或许大家觉得都很简单,一开始我也觉得没什么,不过学生的一个问题,让我觉得有点东西可写!

         传智播客.Net基础班915日的学员问道:“怎样在控制台里面输入密码的时候显示*”。虽然当时很快解决了,不过怎么写的有些学生会更关心。

         我在传智播客教C#基础,主要针对没有基础、没有学过编程的学员来编写课程内容,我常常说基础班要掌握的只有两点:

         第一、面向对象编程思想的理解

         第二、如何写出程序

 

         今天不打算讨论第一个问题,主要说说第二个吧!

         “老师讲的都听得懂,但是自己写就是不会… …”我想大多数学习编程的同学都有这样的问题,所以对于今天学生的这个问题,我把我的分析过程写一下。

 

         首先我本身没有写过代码实现这个功能,但是学生问到了,需要看看用什么样的代码能最简单的做出来,首先对于按下键盘,已经熟悉的方法有两个

    Console.ReadLine();
Console.ReadKey();

 

         但是对于Console.ReadLine()我们了解是针对一行代码,也就是说当按下回车的时候,才会有变化,那么Console.ReadKey()怎么样呢?

 

我新建一个项目,键入代码

class Program
{
static void Main(string[] args)
{
  System.Console.ReadKey();
  System.Console.ReadKey();
}
}

编译运行,等待按下两个键,我们发现按下的键也会在屏幕上显示,那怎么显示*呢?

 

         思考发现按下总会有文字,那要显示别的,不显示文字怎么办?其实和“冒名顶替”倒还是有点像,比如上学的时候“带喊到”的现象大家还是比较清楚地,比如喊道“张三”,但是张三和李四打了招呼,那么李四会帮忙喊到。想想这不就是一样的嘛!

         当按下按键的时候,计算机不显示按键(肯定是先通知了嘛),然后由Console.Write()方法在屏幕上显示一个*,没按一次,显示一个,这样不就好了吗!OK那么思路是有了,下面理一理。

 

步骤可以简化为

-> 首先提示用户输入密码

-> 然后提供输入,但是只记录按下的键,不显示

-> 然后每次按下一个键,输出一个*

那么这里会发现只能输入一个字符,还是不好,那怎么处理可是多次输入,并且按照习惯回车表示结束呢?

         用循环,并当按下回车表示结束,那么可以修改一下上面的步骤

-> 首先提示用户输入密码

-> 写一个循环

-> 然后提供输入,但是只记录按下的键,不显示

-> 然后每次按下一个键,输出一个*

-> 当按下回车跳出循环

那么可以修改我们的项目

class Program
{
static void Main(string[] args)
{
System.Console.WriteLine(“请输入密码”);
while(true)
     {
    
if(如果输入回车)
       {
      
break;
       }
       记录按下的键,但是不显示;
       System.Console.Write(“
*”);
    }
   }
}

用伪代码来实现会一开始写代码轻松许多,但是问题是现在怎么知道我按下的是回车呢?并且怎么才能接收按下一个字符不显示呢?我们接收一个字符只学习了Console.ReadKey(),而刚刚实验了,也是会显示出按下的键啊?

         那么这时既然没有办法了,查看MSDN吧!

         MSDN很强大,只要这么写Console.ReadKey(true)就不会显示按下的任何信息了,并且知道返回按下的Unicode编码,但是Unicode编码又是什么?这里还不知道,但是既然返回,我就找个变量接收。

         了解到Console.ReadKey()返回的类型是ConsoleKeyInfo,那么可以修改一下代码

class Program
{
static void Main(string[] args)
{
System.Console.WriteLine(“请输入密码”);
while(true)
    {
    ConsoleKeyInfo temp
= System.Console.ReadKey(true);
    
if(如果输入回车)
      {
      
break;
      }
      记录按下的键,但是不显示;
      System.Console.Write(“
*”);
    }
  }
}

那么可以记录按下的信息了。但是怎么用呢?试了几次都报错,没办法?先点点看。

key后面加一个“.”会发现一个单词KeyChar,很兴奋,这个就是字符嘛!但是仍然疑虑,那么我们调试一下,在VS里设下断点

这么一来运行到这里,可以看看temp里面的值是多少。

很好,可以看到这里按下回车后,temp里面会记录下来,并且KeyChar里面就是对应的字符,修改代码

using System;
class Program
{
static void Main(string[] args)
  {
  Console.WriteLine(“请输入密码”);
  
while(true)
    {
    ConsoleKeyInfo temp
= Console.ReadKey(true);
    
if(temp.KeyChar == ‘\r’)
      {
      
break;
      }
      记录按下的键,但是不显示;
      System.Console.Write(“
*”);
    }
  }
}

这么一来,只要按下回车就结束了。下面在定义一个字符串,将按下的键记录下来

using System;
class Program
{
static void Main(string[] args)
  {
  
string pwd = “”;
  Console.WriteLine(“请输入密码”);
  
while(true)
    {
    ConsoleKeyInfo temp
= Console.ReadKey(true);
    
if(temp.KeyChar == ‘\r’)
      {
      
break;
      }
      pwd
+= temp.KeyChar.ToString();
      System.Console.Write(“
*”);
    }
    Console.WriteLine(“\n输入成功,你输入的密码是{
0}”,pwd);
    Console.ReadKey();
  }
}

这么一来就OK了,但是用一用又有一个问题,输入错误退格的时候会出现错误

 

         利用设断点的方法可以知道,当按下“退格”键时,Console.ReadKey()中返回了’\b’那么这时怎么实现退格呢?

         我们用现实的方式模拟一下,假设有一行字符串”abcdefg”,显示的是”*******”

         当按下退格键的时候,应该将显示的7*改为6个,光标并停留在第六个后面,并且里面的字符串只能是”abcdef”

         先来看怎么实现去掉一个*,毫无疑问,在控制台中去掉*是不可能的,要么清屏,要么用一个字符去覆盖原有的。这里如果采用第二种方式,也就只有用空格了,那么只需要退一格,输出一个空格,然后再退一格。那么可以添加逻辑

if(temp.KeyChar == ‘\b’)
{
System.Console.Write(“\b \b”);
}

然后就剩下修改存储的字符串了,很简单,只要取出第零个到倒数第二个的即可,因此

if(temp.KeyChar == ‘\b’)
{
System.Console.Write(“
*”);
pwd
= pwd.Substring(0, pwd.Length - 1);
}

这里还需要考虑,如果没有输入任何内容,键入退格,应该改不做任何操作,所以还需要添加代码

if(pwd.Length == 0 && temp.KeyChar == ‘\b’)
{
continue;
}

整合一下代码,就是

using System;
class Program
{
static void Main(string[] args)
  {
  Console.WriteLine(“请输入密码”);
  
string pwd = “”;
  
while(true)
    {
    // ConsoleKeyInfo temp
= Console.ReadKey(); 这行代码有笔误,在此修改20110920
      ConsoleKeyInfo temp = Console.ReadKey(true);
    
if(temp.KeyChar == ‘\b’ && pwd.Length == 0)
      {
      
continue;
      }
      if(temp.KeyChar == ‘\r’)
      {
      
break;
      }
      if(temp.KeyChar == ‘\b’)
      {
      Console.Write(“\b \b”);
      pwd
= pwd.Substring(0, pwd.Length - 1);
      }
      else
      {
      pwd
+= temp.KeyChar.ToString().Trim();
      Console.Write(“
*”);
      }
    }
    // 显示出来填入的密码
    Console.WriteLine(“您输入的密码是{0}”, pwd);
    Console.ReadKey();
  }
}

 

这样就大功告成!偶也!

实际上这段代码还是不好,还有可以优化一下,代码有些冗余,不过对于初学者,这个先练着!












posted @ 2011-09-19 23:24  狄拉克之海  Views(4517)  Comments(22Edit  收藏  举报