直入正题,今天C#上课的时候遇到了一个问题,就是输入console.readLine()调试仍然闪退,对于我这种新手来说,都是拿console.readLine()来当暂停键,还没遇到过这种问题,查了查前辈们的博客,原来是缓冲区在作怪。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test
{
class Program
{
static void Main(string[] args)
{//判断输出
Console.Write("请输入一个字符: ");
char s = Convert.ToChar(Console.Read());//使用Read()会一闪而过
if ((s >= 'a') && (s <= 'z'))
Console.WriteLine("您输入的是小写的字母 {0}", s);
else if (s >= '1' && s < '9')
Console.WriteLine("您输入的是数字 {0}", s);
else if (s >= 'A' && s <= 'Z')
Console.WriteLine("您输入的是大写的字母 {0}", s);
Console.ReadLine();
}
}
}
问题就处在char s = Convert.ToChar(Console.Read()); 这一行代码上,先说一下,这里使用Console.Read()代码会一闪而过,而使用Console.ReadLine()则按如期效果运行,这是为什么呢?下面说一下原理。
每个输入输出流都维护一个字符缓冲区,用于从流接收输入,或者用于输出到流。上面程序在执行char s = Convert.ToChar(Console.Read());后出现一个输入提示符,假如输入'a', 然后回车,相当于输入了'a\r\n',而'a'被读到了s变量里,这时缓冲区里的内容会是'\r\n',即残留了回车键值。Console.ReadLine()每次读取一行,即可以将行尾的回车键读走;Console.Read();每次读取一字符,需要两次将'\r\n'读走,这样才能清空到缓冲区。而把这一句换成char s = Convert.ToChar(Console.ReadLine());后,执行Console.ReadLine()时,缓冲区里有\r\n,它会将缓冲区里 第一个\r\n及其前面的内容(这里是空)读走,不必等待用户输入,用户也就没机会输入了,直接就闪了, 这就是为什么会出现开头所说的输入console.readLine();调试仍然闪退。
如果大家不相信当'a'取走后,缓冲区中还存有\r和\n,我们可以将代码完善一下验证一下嘛!原理就是在不输入的前提下再逐次对缓冲区取三次值并输出(不是说的还有俩嘛?为啥还要取三次呢。当然是为了证明里面有且只有俩喽,第三次应该是啥也取不到),跑一下程序,看一下缓冲区里的庐山真面目吧。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test
{
class Program
{
static void Main(string[] args)
{//判断输出
Console.Write("请输入一个字符: ");
char s = Convert.ToChar(Console.Read());//使用Read()会一闪而过
if ((s >= 'a') && (s <= 'z'))
Console.WriteLine("您输入的是小写的字母 {0}", s);
else if (s >= '1' && s < '9')
Console.WriteLine("您输入的是数字 {0}", s);
else if (s >= 'A' && s <= 'Z')
Console.WriteLine("您输入的是大写的字母 {0}", s);
//////////////////////////////////////////////////////////
// 以下是代码的新增改下部分 //
/////////////////////////////////////////////////////////
string a = Convert.ToString (Console.Read());
Console.WriteLine(a);//取缓冲区里第一个数打印出来
string b = Convert.ToString(Console.Read());
Console.WriteLine(b);//取缓冲区里第二个数打印出来
string c = Convert.ToString(Console.Read());
Console.WriteLine(c);////取缓冲区里第三个数打印出来,应该是没有,啥也取不到
Console.ReadLine();
}
}
}
看一下运行结果吧:
结果正如我们所愿,这次在不输入的前提下再逐次对缓冲区提取字符,第一次提取了一个13,第二次提取了一个10 ,我们知道console.Read();读入字符存的都是字符的ASCII码,而13正是\r的ASCII码,10正是\n的ASCII码。
所以我们在用c#中的 console.Read( )方法的时候一定要注意注意缓冲区赘余的问题。