windows 为什么 Console.Readline 没有按预期执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6048467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is Console.Readline not executing as expected
提问by Kobojunkie
I have the following code below to work with. The problem I have here is that the code runs through the while loop without waiting for input on the line String temp = Console.ReadLine(). Need help understanding why and how to fix please. Thanks in advance!
我有以下代码可以使用。我在这里遇到的问题是代码在 while 循环中运行,而无需等待String temp = Console.ReadLine()行上的输入。需要帮助了解原因和解决方法。提前致谢!
/*Banker's algorithm Implementation*/
class Program
{
static void Main(string[] args)
{
int n = 0;//number of resources we will be dealing with
int proc_num = 0;//Total number of processes to share available resources
IDictionary<String, SysProcess> processes = new Dictionary<String, SysProcess>();
IDictionary<String, int> MaxR = new Dictionary<String, int>();// maximum available resources
IDictionary<String, int> avail = new Dictionary<String, int>();// Available resources after first allocation
Dictionary<String, int> availsum = new Dictionary<string, int>();
//Start
while (true)
{
Console.WriteLine(" What is number of resources to be shared? : ");
if (!int.TryParse(Console.ReadLine(), out n))
{
Console.WriteLine(" Error Please provide valid number --- {0}!", n);
}
else
{
break;
}
}
//get the maximum number of each Resources Ie Total Resources Available
while (true && n>0)
{
Console.WriteLine("Using a comma delimited list(e.g. 0, 0, 0, 0) list maximum of each of the {0} resources : ", n);
String temp;
temp = Console.ReadLine();
if (!String.IsNullOrEmpty(temp))
{
String[] maxR = temp.Split(',');
for (int a = 1; a <= n; a++)
{
MaxR.Add("Resource#" + a.ToString(), Convert.ToInt32(maxR[a]));
}
break;
}
}
while (true && n>0)
{
Console.Write("Enter total number of processes to share the available resources :");
if (!int.TryParse(Console.Read().ToString(), out proc_num))
{
Console.WriteLine(" Error Please provide valid number --- {0}!", proc_num);
}
else
{ break; }
}
if(proc_num > 0)
{
//Request Process Max and allocated resources data
for (int i = 1; i <= proc_num; i++)
{
Console.Write("Using a comma delimited list, Enter total number of Resources 1 through {0} are needed by PROCESS#{1} ?", n, i);
String[] temps = Console.ReadLine().Split(',');
SysProcess tempproc = new SysProcess("Process#" + i.ToString());
for (int a = 0; a < temps.Length; a++)
{
tempproc.Add_max_resource("Resource#" + (a + 1).ToString(), Convert.ToInt32(temps[a]));
}
//How many resources have already been allocated to each resource
temps = null;
Console.Write("Using a comma delimited list,Enter number of resources 1 through {0} already allocated to PROCESS#{1} ? ", n, i);
temps = Console.ReadLine().Split(',');
for (int a = 0; a < temps.Length; a++)
{
tempproc.add_alloc_resource("Resource#" + (a + 1).ToString(), Convert.ToInt32(temps[a]));
}
processes.Add("Process#" + i.ToString(), tempproc);
}
Console.WriteLine("Processing . . . ");
Console.WriteLine();
Console.WriteLine("Available resources ");
//Compute Available Resources
for (int i = 0; i < n; i++)
{
if (!availsum.ContainsKey("Resource#" + (i + 1).ToString()))
availsum.Add("Resource#" + (i + 1).ToString(), 0);
foreach (SysProcess sp in processes.Values)
{ //add sum up the available
availsum["Resource#" + (i + 1).ToString()] += sp.alloc_resources["Resource#" + (i + 1).ToString()];
}
}
//print out the availables we computed
Console.Write(" avail< ");
for (int j = 0; j < n; j++)
{
Console.Write(availsum["Resource#" + (j + 1).ToString()] + ",");
if (j + 1 == n)//if this is the last one, go ahead and output the rest
Console.Write("{0} > ", availsum["Resource#" + (j + 1).ToString()]);
}
// Printing resources still needed
Console.WriteLine();
foreach (SysProcess p in processes.Values)
{
p.print_needed();
}
//a) Find a row in the Need matrix which is less than the Available vector.
//If such a row exists, then the process represented by that row may complete
//with those additional resources. If no such row exists, eventual deadlock is possible.
Dictionary<String, int> _currentavailsum;
foreach (SysProcess p in processes.Values)
{
int TotalSproccounter = 0;
String safelead;
if (isprocessSafe(n, p, availsum))
{
TotalSproccounter++;
safelead = p.id;
_currentavailsum = new Dictionary<String, int>();
_currentavailsum = availsum;//get a copy of the original data to begin with
foreach (SysProcess q in processes.Values)
{
if (q != p)//we only want to compare with the others from here
{
if (isprocessSafe(n, p, _currentavailsum))
{
update_availsum(n, q, ref _currentavailsum);//update the currentavail count
TotalSproccounter++;
//update print
safelead += ", " + q.id;
}
}
}
if (TotalSproccounter == proc_num)
{
Console.WriteLine("Safe allocation < {0} >", safelead);
}
else
{
Console.WriteLine("Deadlock reached/unsafe allocation : < {0} >", safelead);
}
}
}
}
Console.ReadLine();
}
//compares the number of resources needed against the number of resources available
public static Boolean isprocessSafe(int n, SysProcess p, IDictionary<String, int> avail)
{
int safecount = 0;
foreach (String resourcekey in avail.Keys)
{
if (p.need_resources.ContainsKey(resourcekey) && p.need_resources[resourcekey] <= avail[resourcekey])
{
safecount++;
}
}
if (safecount == n)
{
return true;
}
return false;
}
//compares the number of resources needed against the number of resources available
public static void update_availsum(int n, SysProcess p, ref Dictionary<String, int> _currentavailsum)
{
foreach (String resourcekey in _currentavailsum.Keys)
{
if (p.need_resources.ContainsKey(resourcekey))
{
_currentavailsum[resourcekey] += p.need_resources[resourcekey];
}
}
}
}
//container class for processes
public class SysProcess
{
public String id { get; set; }
Dictionary<String, int> _max_resources = null; // will hold the Resource name and the the number of resources
Dictionary<String, int> _alloc_resources = null;//allocated resources
Dictionary<String, int> _need_resources = null;//allocated resources
public Dictionary<String, int> max_resources
{
get
{ return _max_resources; }
}
public Dictionary<String, int> alloc_resources
{
get
{
return _alloc_resources;
}
}
public Dictionary<String, int> need_resources
{
get
{
return _need_resources;
}
}
public SysProcess(String procID)
{
_max_resources = new Dictionary<String, int>();
_alloc_resources = new Dictionary<String, int>();
id = procID;
}
public void Add_max_resource(String resource, int count)
{
_max_resources.Add(resource, count);
}
public void add_alloc_resource(String resource, int count)
{
_alloc_resources.Add(resource, count);
_need_resources.Add(resource, _max_resources[resource] - alloc_resources[resource]);
}
public void print_needed()
{
Console.Write(id);
foreach (int s in _need_resources.Values)
{
Console.Write(" {0}", s);
}
}
}
Probably a good idea to add the whole code here since I am still unable to figure this one out. Please help
在这里添加整个代码可能是个好主意,因为我仍然无法弄清楚这一点。请帮忙
回答by Jeffrey L Whitledge
The problem is the use of the problematic method Console.Read()
. This method will block until a full line of text is entered, but it only returns the first character, leaving the remaining text in the input buffer. The carriage return that was used to enter the first value and unblock the read operation is still sitting in the input buffer when the Console.ReadLine()
operation is performed. Consequently, a blank line is returned.
问题是使用了有问题的方法Console.Read()
。此方法将阻塞,直到输入一整行文本,但它只返回第一个字符,将其余文本留在输入缓冲区中。执行操作时,用于输入第一个值并取消阻止读取操作的回车符仍位于输入缓冲区中Console.ReadLine()
。因此,返回一个空行。
I recommend that you replace Console.Read().ToString()
with Console.ReadLine()
to fix this problem.
我建议您替换Console.Read().ToString()
为Console.ReadLine()
以解决此问题。
The problem can be demonstrated with this code:
可以使用以下代码演示该问题:
static void Main(string[] args)
{
string value = Console.Read().ToString();
Console.WriteLine("You entered: {0}", value);
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine(); // Returns immediately.
Console.WriteLine("Continuing....");
}
And fixed like this:
并像这样固定:
string value = Console.ReadLine();
回答by dthorpe
Is your project configured as a console application? It needs to be built with different switches in order to set the flags in the exe file so that the OS loader will know that it needs to create a console window for the process. GUI apps don't set that flag, and don't get a console window.
您的项目是否配置为控制台应用程序?它需要使用不同的开关构建,以便在 exe 文件中设置标志,以便操作系统加载程序知道它需要为进程创建一个控制台窗口。GUI 应用程序不会设置该标志,也不会获得控制台窗口。
In VS2010, right click on your project's Properties link, click on the Application tab, and change Output Type from Windows Application to Console Application. Rebuild and run.
在 VS2010 中,右键单击项目的属性链接,单击应用程序选项卡,然后将输出类型从 Windows 应用程序更改为控制台应用程序。重建并运行。
回答by Gary McConnell
The issue could be stuff already in the input stream you're trying to read from the console. If you don't want to worry about what's already in the buffer, you can try to flush it so that you start with a fresh, empty input state. Offhand, all the Console.Read* functions appear to be blocking functions. However, there's also the KeyAvailable property which indicates if there is content available.
问题可能是您尝试从控制台读取的输入流中已经存在的内容。如果您不想担心缓冲区中已有的内容,可以尝试刷新它,以便从一个全新的空输入状态开始。顺便说一句,所有 Console.Read* 函数似乎都是阻塞函数。但是,还有 KeyAvailable 属性指示是否有可用的内容。
This provides for the following code:
这提供了以下代码:
private void clearInputBuffer()
{
while(Console.KeyAvailable)
{
Console.Read(); // read next key, but discard
}
}
Alternatively, the buffer for input is, at the basic level, a stream. A TextReader, to be specific. And that is available from
或者,在基本级别上,用于输入的缓冲区是一个流。一个 TextReader,具体来说。这可以从
Console.In
So you can use the functions there, such as .ReadToEnd(), to clear out the buffer right before you enter in your While(true) loop.
因此,您可以使用那里的函数,例如 .ReadToEnd(),在您进入 While(true) 循环之前清除缓冲区。
回答by James Johnston
You probably have duplicate / extra newlines in your input. This code looks perfectly fine for parsing a comma-delimited file...
您的输入中可能有重复/额外的换行符。这段代码看起来非常适合解析逗号分隔的文件......
回答by Jim Mischel
The problem is that you're misinterpreting what Console.Read
does. It reads the next character from the input stream and returns it as an integer. But ... and here's the good part, nothing comes in until you hit Enter. So if you enter "abc" at the first prompt and press Enter, you're going to get the first character from the buffer, as an integer (97). But the input buffer will contain "bc" and the newline, which will then be consumed by the Readline
.
问题是你误解了什么Console.Read
。它从输入流中读取下一个字符并将其作为整数返回。但是......这是好的部分,在你按下 Enter 之前什么都没有。因此,如果您在第一个提示处输入“abc”并按 Enter,您将从缓冲区中获取第一个字符,即整数 (97)。但是输入缓冲区将包含“bc”和换行符,然后将被Readline
.
If you want a string from the Console
, call ReadLine
, not Read
.
如果您想要来自 的字符串Console
,请调用ReadLine
,而不是Read
。