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


或许大家觉得都很简单,一开始我也觉得没什么,不过学生的一个问题,让我觉得有点东西可写!
传智播客.Net基础班9月15日的学员问道:“怎样在控制台里面输入密码的时候显示*”。虽然当时很快解决了,不过怎么写的有些学生会更关心。
我在传智播客教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(); 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(); } }

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

Tags:  显示器控制台 控制台输入数组 控制台输入 控制台输入法 显示控制台

延伸阅读

最新评论

发表评论