Console.Read is being ignored [duplicate] - c#

This question already has answers here:
Console.Read not returning my int32 [duplicate]
(7 answers)
Closed 1 year ago.
I'm new to the C# language, and have only started learning it for use on the XNA Game Studio for X-box.
I have some minor experience with Java and C++, so I'm not a TOTAL noob. That's exactly why this problem is so frustrating to me.
I have created a simple code designed to add two numbers input from the user. Extremely simple stuff, but a good first step for any new language I feel.
I've declared my variables, and was trying to use Console.Read() to get numbers from the user to add. So far, the code outputs the message I want, then stops and reads in a single input from the user. After that, it messes up. The console outputs the next message, reads some random number (no input), then adds them together and outputs that instantly.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Add
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please enter the first number to add: ");
int firstNumber = Console.Read();
Console.WriteLine("Please enter the second number to add: ");
int secondNumber = Console.Read();
int Sum = firstNumber + secondNumber;
Console.WriteLine("The total of the two numbers is: " + Sum);
}
}
}
Sample runs:
Please enter the first number to add:
2
Please enter the second number to add:
The total of the two numbers is: 63
Please enter the first number to add:
3
Please enter the second number to add:
The total of the two numbers is: 64
It continues like that, acting as though the secondNumber is 61.
Thanks in advance for any help!

That's because it is reading the next character from the console and then converting it to int, which gives the ASCII value, not the numeric value. So typing 2 will be interpreted as the character '2', with the ascii code 50. Try this instead:
int firstNumber = Int32.Parse(Console.ReadLine());

Console.Read reads a single character. So when you enter "2" and hit Enter, you're supplying (1) the character '2', whose ASCII value is 50, and then (2) the carriage-return character, whose ASCII value is 13. The sum of these is ... 63. :-)

In addition to what Gareth said, maybe the MSDN information will clear up to you why it's not waiting for your input on the second Console.Read() method:
Console.Read()
The Read method blocks its return while you type input characters; it terminates when you press the Enter key. Pressing Enter appends a platform-dependent line termination sequence to your input (for example, Windows appends a carriage return-linefeed sequence). Subsequent calls to the Read method retrieve your input one character at a time. After the final character is retrieved, Read blocks its return again and the cycle repeats.
So, on your first Read() it's happily allowing you to enter whatever you want until you hit Enter
Then, it gets to the second Console.Read() and says, "Hey, I already have those characters from the first Console.Read() to go through. It just happens that the second one is whitespace (the carriage return)" and it assigns that whitespace ASCII value to secondNumber.

The problem is that Console.Read() reads the first Return keypress and sends that to the second Console.Read() call. Your code should use ReadLine() instead and look something like this:
Console.WriteLine("Please enter the first number to add: ");
int firstNumber = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please enter the second number to add: ");
int secondNumber = Convert.ToInt32(Console.ReadLine());

Console.Read reads a single character from the input block. If you enter a number and then press the enter key it will read the enter key, or the next digit of the first number you entered.
You will likely want to use Console.ReadLine instead.

I think you want the Console.ReadLine() Method

You should Try Console.ReadLine();

You probably want ReadLine not Read as Read takes the next character in the stream, but ReadLine will wait for the user to press enter.
This would cause a bug if your user type 34 the first time, because firstNumber equal 3 not 34.

Related

C# - Multiple Errors

After writing my second program in C#, I receive an error:
Error in Compiler
The error might pertain to the library
or it might be on the Conversion
or the namespace
using System;
namespace MagpantayUserInfoProg {
class UserInfo {
static void Main() {
string name, gender; // Variables for storing words
int contact, age; // Variables for storing integers
Console.Write("Name: "); // Let the user input his name
name = Console.ReadLine(); // System reads data
Console.Write("Gender: "); // Let the user input his gender
gender = Console.ReadLine();// System reads data
Console.Write("Age: "); // Let the user input his age
age = Int32.Parse(Console.ReadLine()); // System reads data
Console.Write("Mobile Number: "); // Let the user input his contact number
contact = Int32.Parse(Console.ReadLine()); // System reads data
// Display Output
Console.Write("Name: {0}\n", name);
Console.Write("Gender: {0}\n", gender);
Console.Write("Age: {0}\n", age);
Console.Write("Mobile Number: {0}\n", contact);
Console.ReadLine();
}
}
}
mobile number too large for int
https://learn.microsoft.com/tr-tr/dotnet/csharp/language-reference/builtin-types/integral-numeric-types
check int range
also use string for storing mobile number
Let's dissect the error message:
Value was either too large or too small for an Int32
So, that tells us the problem is somewhere where we're creating an Int32, and Int32.Parse(Console.ReadLine()); fits the bill, not only are we creating an Int32 here, but this is also the point in the program where the error (exception) is encountered (thrown). But why? Well, because computers don't have infinite memory, so a while ago people (read: software developers) decided on a bunch of standards on how to represent data inside a computer, and those standards contain limits, and the limit for an Int32 (which by the way is the standard int in C#) is no smaller than -2,147,483,648 and no larger than 2,147,483,647 (source), but your phone number is 09,563,977,528, larger than the maximum allowed, and hence the error.
So what do we do now? Well, we could use a larger integral type, like long and Convert.ToInt64, but that's just a band aid solution, instead we should use a string (or a more specialized data structure*). Think about it, is a phone number really just a number? No, it isn't, for one the phone numbers 09563977528 and 9563977528 aren't the same right? But if they're were regular old numbers, they would be, 02 and 2 are the exact same number. Additionally, it doesn't really make sense to use arithmetic operations on phone numbers, there's never a need to multiply or subtract or add or whatever 2 phone numbers together. So for those reasons, I'd suggest we just leave phone numbers as strings.
* A good exercise for when you learn about classes and structs would be to implement a custom class representing a phone number
As others have pointed out, the number is too large to be stored as an Int (Int32) value which can handle any number between
-2,147,483,648 and 2,147,483,647
Generally, you should not store a phone number as a numeric value anyway, because many phone numbers include a leading zero which is critical but cannot be stored if you store the value as a number. But as not all phone numbers do include a leading zero, then you can't assume that there always is one.
So then you need to store this as a string value instead, and then include some validation to ensure that only numbers are entered.
There are many different ways to do this, so you can investigate further to see which suits you, but as an example you can try this, which will scan the string to check that each character is a digit.
Console.Write("Mobile Number: "); // Let the user input his contact number
contact = Console.ReadLine(); // System reads data
if (contact.All(char.IsDigit))
{
// String only contains numbers
}
else
{
//Handle error here
}
Edit:
Of course this solution only allows digit. So if the user wishes to prefix a country code using a '+', then this will not be supported. So then you need to change the solution to support this.
Also, FYI: You don't have a compiler error, you have a runtime exception.

Make a method that checks if the user input is equal to a random number [duplicate]

This question already has answers here:
random number guessing game
(8 answers)
Random Number Guessing Game C#
(3 answers)
C# Guess random number
(2 answers)
Closed 4 years ago.
I have this exercise:
Make a method that generates a random number between 1 and 100.
Ask the user to guess a number between 1 and 100.
Make a method that checks if the user's guess is equal to the random number that has been generated. This method will also say "higher" or "lower" until the user guesses the random number.
I have no problem with steps 1 and 2, but I'm having problems with the 3rd step. Here is my code so far:
static void Main(string[] args)
{
int randomNumber = GenerateRandomNumberMethod();
Console.WriteLine("Guess a number between 1 and 100:");
}
// generate random number method (step 2)
public static int GenerateRandomNumberMethod()
{
Random rdn = new Random();
int random = rd.Next(1,100);
return random;
}
//step 3 (Method to compare guessed number with random number)?
I hope it is not a stupid question, the answer is probably pretty simple.
Well, the first thing you want to do is to store the generated random number in a variable, so that it will not be re-generated after each time the user attempts.
The second thing you want to do is to create a method that will compare the user input against the randomly-generated number, and return a value indicating if the user input is smaller, equal, or higher than the generated number (A bool? might be a good choice for this).
The third thing you need is a safe way to convert the string the user entered to an int.
Do not make the common mistake of using Convert.ToInt32 - use int.TryParse instead. You do not want to throw an exception if the user entered Zohar instead of 123.
The fourth thing to do is to implement a loop - that will keep getting inputs from the user and tell them if the number is too high or too low. Exit the loop if the number is the same as the generated random number.
The last thing to do is to tell the user they finally guessed the correct number and exit (or maybe restart) the game.
Since it's clearly a homework assignment, I'll leave the coding part for you to handle, because you will not learn anything if you don't at least do it yourself, but at least now you have a plan.
Try
int userGuess = int.Parse(Console.ReadLine());
See this previous question on reading user input.
See this previous question on your exact problem.
See comments for note on int.Parse()

Console pause c#

In this code
Console.Write("Enter any number from 0 to 9:");
int k = Console.Read();
Console.Write("The ASCII code for it is:");
Console.WriteLine(k);
Console.Read();
after I input a number my console close instantly.
If I write this code
Console.Write("Enter any string:");
string k = Console.ReadLine();
Console.Write("Your string is:");
Console.WriteLine(k);
Console.Read();
my console stops so I can see what I wrote.
Why is that happening?
Try using the following instead of Console.ReadLine();
Console.ReadKey();
This will wait for your console to input any key before closing.
ReadLine, Read etc. should work but you can also run it via Ctrl-F5 instead, which will keep the window open until you hit a key. Or remove the ReadLine at the end completely if you just want it to close.
Note Ctrl-F5 is running without debugging. If you're after breakpoints don't do this.
Although with your code you're only going to going to get the behaviour you expect from the .Read on line 2.
num=Console.Read();
I think it will be the ASCII code for the first 'character' of your number i.e. if you enter 322 it will just read 3 and the ASCII for 3 is 51, which will be what is assigned to num.

Console Application - WriteLine above current working line

I have seen a few other posts very similar to this one, but the answers they give are not correctly answering the question. Sorry if there is something hidden away that I couldnt find...
I want to use Console.WriteLine() to print something above my current Console.ReadLine(), for example, my app prints "Hello world" and starts a thread that (in 5 seconds) will print "I just waited 5 seconds" above the line where I need to input something, like this:
Hello world
Please input something: _
Then 5 seconds will pass and it will look like this:
Hello world
I just waited 5 seconds
Please input something: _
So far I've tried using Console.SetCursorPosition(0,Console.CursorTop - 1) but this just prints over the line "Please input something: _" and if I use Console.CursorTop - 2 instead it crashes saying "[2] Out of range" (no idea why this is) and if I use Console.CursorTop - 2 it prints under "Please input something: _"... so my question is how do I print something ABOVE the line "Please input something: _"
Just moving the cursor is not good enough, the problem is that you are inserting text. That is possible, the Console.MoveBufferArea() method gives you access to the underlying screen buffer of the console and lets you move text and attributes to another line.
There are a couple of tricky corner-cases. One you already found, you have to force the console to scroll if the cursor is located at the end of the buffer. And the timer is a very difficult problem to solve, you can only really do this correctly if you can prevent Console.ReadLine() from moving the cursor at the exact same time that the timer's Elapsed event inserts the text. That requires a lock, you cannot insert a lock in Console.ReadLine().
Some sample code you can play with to get you there:
static string TimedReadline(string prompt, int seconds) {
int y = Console.CursorTop;
// Force a scroll if we're at the end of the buffer
if (y == Console.BufferHeight - 1) {
Console.WriteLine();
Console.SetCursorPosition(0, --y);
}
// Setup the timer
using (var tmr = new System.Timers.Timer(1000 * seconds)) {
tmr.AutoReset = false;
tmr.Elapsed += (s, e) => {
if (Console.CursorTop != y) return;
int x = Cursor.Left;
Console.MoveBufferArea(0, y, Console.WindowWidth, 1, 0, y + 1);
Console.SetCursorPosition(0, y);
Console.Write("I just waited {0} seconds", seconds);
Console.SetCursorPosition(x, y + 1);
};
tmr.Enabled = true;
// Write the prompt and obtain the user's input
Console.Write(prompt);
return Console.ReadLine();
}
}
Sample usage:
static void Main(string[] args) {
for (int ix = 0; ix < Console.BufferHeight; ++ix) Console.WriteLine("Hello world");
var input = TimedReadline("Please input something: ", 2);
}
Note the test on the Console.Top property, it ensures that nothing goes drastically wrong when the user typed too much text and forced a scroll or if Console.ReadLine() completed at the exact same time that the timer ticked. Proving that it is thread-safe in all possible cases is hard to do, there will surely be trouble when Console.ReadLine() moves the cursor horizontally at the exact same time that the Elapsed event handler runs. I recommend you write your own Console.ReadLine() method so you can insert the lock and feel confident it is always safe.
You can use carriage-return (\r, or U+000D) to return the cursor to the start of the current line, and then overwrite what's there. Something like
// A bunch of spaces to clear the previous output
Console.Write("\r ");
Console.WriteLine("\rI just waited 5 seconds");
Console.Write("Please input something: ");
However, if the user has started typing already this won't work anymore (as you may not overwrite all they have typed, and they will lose what they've typed on the screen, although it's still there in memory.
To properly solve this you actually need to modify the console's character buffer. You have to move everything above the current line one line up, and then insert your message. You can use Console.MoveBufferArea to move an area up. Then you need to save the current cursor position, move the cursor to the start of the line above, write your message, and reset the cursor position again to the saved one.
And then you have to hope that the user doesn't type while you're writing your message, because that would mess things up. I'm not sure you can solve that while using ReadLine, though, as you cannot temporarily lock something while ReadLine is active. To properly solve that you may have to write your own ReadLine alternative that reads individual keypresses and will lock on a common object when writing the resulting character to avoid having two threads writing to the console at the same time.

I'm trying to to use ReadLine(), or Read() or ReadKey to read in integers using C#

I'm new to C# and I'm having some trouble reading some ints out of a Console Window App. What I need to do is have a user enter in some integers and press spacebar and enter more numbers and I need to evaluate the numbers one at a time on the fly without the user pressing Enter. I then have to do so other stuff with the numbers but that's not an issue.
Should I use Console.Read() or Console.ReadKey(), I know ReadLine() wont do anything until enter is pressed so wont do what I want.
For your case, ReadKey is more suitable than Read() since the Read terminates when you press the Enter key. But ReadKey() is like below:
The ReadKey method waits, that is, blocks on the thread issuing the ReadKey method, until a character or function key is pressed. A character or function key can be pressed in combination with one or more Alt, Ctrl, or Shift modifier keys. However, pressing a modifier key by itself will not cause the ReadKey method to return.
Hope This will be helpful for you
Difference between Console.Read() and Console.ReadLine()?
As I understand your question you can use Console.ReadLine() instead of using Console.Read()...Give me further details to update more...
I ended up using a ReadKey(), which seemed to work well. Thanks for the help anyway.
numberIntoConsole = Console.ReadKey();
numberReceived = (int)Char.GetNumericValue(numberIntoConsole.KeyChar);
if (numberReceived != -1) //checks to see if a spacebar was pressed
{
if(numberReceived == lastNumberEntered) //checks if numberReceived is equal to lastNumberEntered
{
lastNumberEntered = numberReceived; //make the lastNumberEntered the same as numberReceived
++numberChecker; // add to the numberChecker
} else // else we restart the counter
{
numberChecker = 1;
lastNumberEntered = numberReceived;
}
}

Categories