Checking each value of a console output - c#

I would like to read each value one by one, every single one they keep typing until they press a value which ends the "input checking".
I have checked several other posts but none works for me, because I don't want to use arrays or lists, the value must be checked once, and if that happens then work with that.
I have managed to achieve this:
char END = '#', value;
bool found= false;
int count = 0;
Console.WriteLine("Write a line ending in '#'.");
value = Convert.ToChar(Console.Read());
if (value == END)
found = true;
while (!found)
{
count++;
value = Convert.ToChar(Console.Read());
if (value == END)
found = true;
}
}
Console.WriteLine("You have typed " + count);

You should use StringBuilder object, you can add characters one by one to it. I have also simplified your logic a lot.
char END = '#';
var sb = new StringBuilder();
Console.WriteLine("Write a line ending in '#'.");
while (true)
{
var ch = Convert.ToChar(Console.Read());
if (ch == END)
break;
sb.Append(ch)
}
}
Console.WriteLine("You have typed " + sb.ToString());

Something like this.
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
Console.WriteLine("Write a line ending in '#'.");
ConsoleKeyInfo keyInfo;
do
{
keyInfo = Console.ReadKey();
// Evaluate Input Key
if (int.TryParse(keyInfo.Key.ToString(), out int i))
{
; // do something with an int
}
else
{
; // do something with char
}
if (keyInfo.KeyChar != '#')
{
sb.Append(keyInfo.KeyChar);
}
}
while (keyInfo.KeyChar != '#');
Console.WriteLine();
Console.WriteLine($"You typed '{sb.ToString()}' which is {sb.Length.ToString()} character(s).");
Console.WriteLine("Press any key to exit.");
Console.ReadLine();
}

Related

C# Console application crashing before if statement can run

static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("1. SHC ");
int UserInput1 = Console.Read();
if (UserInput1 == 1)
{
Console.WriteLine("Mass (kg): ");
int shcmass = Console.Read();
Console.WriteLine("Specific Heat Capactiy (J/Kg/°C): ");
int shcshc = Console.Read();
Console.WriteLine("Temperature Difference (△Ø): ");
int shctemp = Console.Read();
int shcfinal = shcmass * shcshc * shctemp;
Console.WriteLine("Energy: " + shcfinal);
}
This is the code I am using within a small console application. I don't know if I am missing something but every time I run it, the first bit works where it says "1. SHC" and gives time for the user input. But once entered the console application dies and I cannot figure out why.
There's nothing stopping the console application to close, add a Console.ReadLine() at the end of your mainloop. I'd recommend using ReadLine() over reads for other input as well, but it would depend on your needs. If you see from the "Remarks" section of the Console.Read documentation it's preferable to use ReadLine()
e.g.
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("1. SHC ");
int UserInput1 = int.Parse(Console.ReadLine());
if (UserInput1 == 1)
{
Console.WriteLine("Mass (kg): ");
int shcmass = int.Parse(Console.ReadLine());
Console.WriteLine("Specific Heat Capactiy (J/Kg/°C): ");
int shcshc = int.Parse(Console.ReadLine());
Console.WriteLine("Temperature Difference (△Ø): ");
int shctemp = int.Parse(Console.ReadLine());
int shcfinal = shcmass * shcshc * shctemp;
Console.WriteLine("Energy: " + shcfinal);
}
Console.ReadLine();
}
Console.Read() returns
The next character from the input stream, or negative one (-1) if
there are currently no more characters to be read.
https://msdn.microsoft.com/en-us/library/system.console.read(v=vs.110).aspx
You will need
ch = Convert.ToChar(x);
Excerpt:
class Sample
{
public static void Main()
{
string m1 = "\nType a string of text then press Enter. " +
"Type '+' anywhere in the text to quit:\n";
string m2 = "Character '{0}' is hexadecimal 0x{1:x4}.";
string m3 = "Character is hexadecimal 0x{0:x4}.";
char ch;
int x;
//
Console.WriteLine(m1);
do
{
x = Console.Read();
try
{
ch = Convert.ToChar(x);
if (Char.IsWhiteSpace(ch))
{
Console.WriteLine(m3, x);
if (ch == 0x0a)
Console.WriteLine(m1);
}
else
Console.WriteLine(m2, ch, x);
}
catch (OverflowException e)
{
Console.WriteLine("{0} Value read = {1}.", e.Message, x);
ch = Char.MinValue;
Console.WriteLine(m1);
}
} while (ch != '+');
}
}
I've had similar issues before. When using Console.Read() after Console.WriteLine() you'll end up reading '\r' which is what causes the crash I believe. Try using Console.ReadKey() instead.

Program skips lines of code

I have a small program that changes values of char arrays. But first you need to tell the program in which array you want to change a value; and write a new value and its position into that same array position.
But when I enter the array number, the program skips the code lines allowing the entry of the new value and its position. Then the program throws a FormatException at the end.
Here's the code:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
Console.Write("- Message #: ");
Mnumber = (char)Console.Read();
if (Mnumber == '1')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageOne[position - 1] = letter;
}
if (Mnumber == '2')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageTwo[position - 1] = letter;
}
}
static void Main(string[] args)
{
char[] array1 = new char[50];
char[] array2 = new char[50];
for (int i = 0; i < 50; i++)
{
array1[i] = '*';
array2[i] = '*';
}
addLetters(array1, array2);
}
}
P.S. Could you please tell me how I can make this code more 'elegant'?
When reading a single character it's reccommended to use Console.ReadKey().KeyChar. I've modified your code to handle exceptions as well:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
try
{
do
{
Console.Write("- Message #: ");
Mnumber = Console.ReadKey().KeyChar;
Console.WriteLine();
}
while (Mnumber != '1' && Mnumber != '2');
Console.Write("\nLetter: ");
letter = Console.ReadKey().KeyChar;
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
if (Mnumber == '1')
messageOne[position - 1] = letter;
else
messageTwo[position - 1] = letter;
}
catch (FormatException)
{
Console.WriteLine("Invalid input format, position must be an integer");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Position out of array bounds");
}
finally
{
Console.Read();
}
}
Try a single function for both messages, and TryParse() your string to integer conversions
static char ReadChar(string prompt)
{
// Screen Prompt
Console.Write(prompt);
// Read a Character
return Console.ReadKey(false).KeyChar;
}
static int ReadNumber(string prompt)
{
// Screen Prompt
Console.Write(prompt);
int result=-1;
// Reads a number and onverts it into an integer
int.TryParse(Console.ReadLine(), out result);
return result;
}
// Caution, this modifies the contents of `messages`
static void addLetters(params char[][] messages)
{
// Read message index (first=1, second=2, etc)
int Mnumber=ReadNumber("- Message #: ");
// Read letter
char letter=ReadChar("Letter: ");
// Read placement position
int position=ReadNumber("\nPosition: ");
// Get the right message
char[] current_message=messages[Mnumber-1];
// Assigns a letter to the message
current_message[position]=letter;
}
static void Main(string[] args)
{
int n=50; //Store the size instead of hard coding it all over your code
char[] array1=new char[n];
char[] array2=new char[n];
for (int i=0; i<n; i++)
{
array1[i]='*';
array2[i]='*';
}
addLetters(array1, array2);
}

Cannot convert system.consolekeyinfo to string

What I'am trying to achieve here is that when you press "1" it will check it against "code_1" and then if it matches it will say "key1 correct" and then check the other codes. But the compiler says
Cannot convert system.consolekeyinfo to string
so I'm wondering how I fix this. Here is the code that I use :
static void Main(string[] args)
{
string first_time = null;
string paktc = "Press any key to continue . . .\r\n";
string code_1 = "1";
string code_2 = "2";
string code_3 = "3";
string code_4 = "4";
if (first_time == null)
{
Console.WriteLine("\r\nYour code is 1234\r\n");
Console.WriteLine(paktc);
Console.ReadKey();
Console.WriteLine("Insert Code Now\r\n");
ConsoleKeyInfo key1 = Console.ReadKey();
if (code_1 = key1)
{
ConsoleKeyInfo key2 = Console.ReadKey();
if (code_2 = key2)
{
ConsoleKeyInfo key3 = Console.ReadKey();
if (code_3 = key3)
{
Console.WriteLine("Key3 Correct\r\n");
ConsoleKeyInfo key4 = Console.ReadKey();
if (code_4 = key4)
{
Console.WriteLine("Key4 Correct\r\n");
Console.ReadKey();
Console.WriteLine(paktc);
}
else
{
}
}
else
{
}
}
else
{
}
}
else
{
}
}
}
}
The error you are currently getting is because you forgot that:
= and == are NOT the same thing. The first is assignment, the second is comparison.
And you can't assign a string to a ConsoleKeyInfo, or vice versa, and definitely not in an if statement. Even if you had fixed that however, you still can't compare a string to a ConsoleKeyInfo. You can get its KeyChar property and compare that to a char though:
if (keyInfo.KeyChar == myString[0])
is valid (as string can be indexed to get its chars). In your case, you can just use a char and make it much simpler:
if (keyInfo.KeyChar == '1')
ToString() would work. Say we have ConsoleKeyInfo j.
It'll look like string k = j.KeyChar.ToString();
This will do exactly what you want.
So the code will look like:
ConsoleKeyInfo key1 = Console.ReadKey();
if (code_1 == key1.KeyChar.ToString())
{
//Other stuff here as follows.
}
You could even do this.
if (key1.KeyChar.ToString() == "1")
{
//Other stuff here as follows
}
Use Console.Read(); instead, it returns a int witch can be typecasted into a char. Also instead of having 4 strings with one character in them, you can have one string with the full code in it and use it as an array, See the example below
static void Main(string[] args)
{
string pw = "123";
Console.WriteLine("Enter the first digit of the password");
char toTest = (char) Console.Read();
Console.Read();
Console.Read();
if (toTest == pw[0])
{
Console.WriteLine("Enter the second digit of the password");
toTest = (char)Console.Read();
Console.Read();
Console.Read();
if (toTest == pw[1])
{
Console.WriteLine("Enter the third digit of the password");
toTest = (char)Console.Read();
Console.Read();
Console.Read();
}
}
}
The extra Console.Read(); commands are to catch the invisible characters that are inputted when pressing enter.

How to assign a value read from the console to an integer field?

In my hangman game, I am attempting to prompt the user to enter the number of "lives" (or guesses) the player should be given. After I type a number at the prompt, the following error message is displayed:
Cannot implicitly convert type 'int' to 'string'
The following line causes the error:
lives = Console.ReadLine();
The lives field is an integer. How can I correctly assign a user-entered value to an integer field?
Here is my complete code:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class Hangman
{
//guesses
public static int lives = 5;
//Words for the game
static string[] wordBank = { "study", "cat", "dress", "shoes", "lipstick" };
// Create new ArrayList and initialize with words from array wordBank
static ArrayList wordList = new ArrayList(wordBank);
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Title = "C# Hangman";
Console.WriteLine("Hang man!");
//Gamemenu
string response = "";
do
{
Console.Write("Enter Command (1. Add Words, 2. List Words , 3. Play , 4. Exit) Pick 1-4: ");
response = Console.ReadLine();
switch (response)
{
case "1": AddWord(); break;
case "2": ListWords(); break;
case "3": Play(); break;
case "4": break;
}
} while (response != "4");
}
//add words to list
static void AddWord()
{
Console.Write("Enter the word to add: ");
String temp = Console.ReadLine();
wordList.Add(temp);
Console.WriteLine("{0} was added to the dictionary!", temp);
}
//Display words
static void ListWords()
{
foreach (Object obj in wordList)
Console.WriteLine("{0}", obj);
Console.WriteLine();
}
//How many guesses
static void AskLives()
{
try
{
Console.WriteLine("please enter number of lives?");
//This line gives me the error
lives = Console.ReadLine();
}
catch
{
// if user does not enter a number ask it again
AskLives();
}
}
//Gameplay
static void Play()
{
Random random = new Random((int)DateTime.Now.Ticks);
string wordToGuess = wordList[random.Next(0, wordList.Count)].ToString();
string wordToGuessUppercase = wordToGuess.ToUpper();
StringBuilder displayToPlayer = new StringBuilder(wordToGuess.Length);
for (int i = 0; i < wordToGuess.Length; i++)
displayToPlayer.Append('-');
List<char> correctGuesses = new List<char>();
List<char> incorrectGuesses = new List<char>();
bool won = false;
int lettersRevealed = 0;
string input;
char guess;
AskLives();
while (!won && lives > 0)
{
Console.WriteLine("Current word: " + displayToPlayer);
Console.Write("Guess a letter: ");
input = Console.ReadLine().ToUpper();
guess = input[0];
if (correctGuesses.Contains(guess))
{
Console.WriteLine("You've already tried '{0}', and it was correct!", guess);
continue;
}
else if (incorrectGuesses.Contains(guess))
{
Console.WriteLine("You've already tried '{0}', and it was wrong!", guess);
continue;
}
if (wordToGuessUppercase.Contains(guess))
{
correctGuesses.Add(guess);
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuessUppercase[i] == guess)
{
displayToPlayer[i] = wordToGuess[i];
lettersRevealed++;
}
}
if (lettersRevealed == wordToGuess.Length)
won = true;
}
else
{
incorrectGuesses.Add(guess);
Console.WriteLine("Nope, there's no '{0}' in it!", guess);
lives--;
}
Console.WriteLine(displayToPlayer.ToString());
}
if (won)
Console.WriteLine("You won!");
else
Console.WriteLine("You lost! It was '{0}'", wordToGuess);
Console.Write("Press ENTER to exit...");
Console.ReadLine();
}
}
}
Your lives field is an integer, but Console.ReadLine returns a string.
You can use Int32.Parse(Console.ReadLine()) to parse the input into an integer. Note that an exception will be thrown if the text entered by the user cannot be interpreted as an integer.
Your catch block will work here and re-prompt. It would be more appropriate to use the Int32.TryParse method:
int tmpLives;
if (Int32.TryParse(Console.ReadLine(), out tmpLives))
{
lives = tmpLives;
}
else
{
AskLives();
}
You want to do something along the lines of:
string livesString = Console.ReadLine();
lives = Convert.ToInt32(livesString);
I'm guessing Console.ReadLine() gives you a string. This will not play ball with your integer lives. You could try this:
lives = Int.Parse(Console.ReadLine())

How to read characters from the keyboard until a period is received, and count the number of spaces

I'm very new to C# and OOP and stackoverflow. This is my first scenario (a few questions)
I want the user to enter characters, until a period (.) is received, and to count and report the number of whitespaces.
Can I achieve this?
(Not sure if you always hit to hit enter/return to send)
Can I do this without using strings?
(I haven't covered strings yet, this is a self-learning exercise, and I believe the solution should therefore be very simple, but I'm getting unusual results).
I tried the following, but the program closes before I can see the results, even though I added a Console.Read(); at the end, which usually works...
class CountSpaces
{
static void Main(string[] args)
{
Console.WriteLine("Enter characters,finish with a period (\".\"");
char ch;
int spaces=0;
do
{
ch = (char)Console.Read();
if (ch == ' ')
{
spaces++;
}
} while (ch != '.');
Console.WriteLine("Number of spaces counted = {0}",spaces);
Console.Read();
}
}
Use Console.ReadKey() instead of Console.Read().
Console.ReadKey() returns if a key has been pressed between after you called Console.ReadKey().
Console.Read() reads the character as in a stream (not useful at all in your case).
To get the char received by ReadKey, use : ch = Console.ReadKey().KeyChar;
You want ReadKey rather than Read. The latter just reads the next character if it exists on the stream and returns -1 if it doesn't as it won't wait (and you probably aren't typing that fast!)
If all you want is to see the result you just use ReadKey instead:
class CountSpaces
{
static void Main(string[] args)
{
Console.WriteLine("Enter characters,finish with a period (\".\"");
char ch;
int spaces = 0;
do
{
ch = (char)Console.Read();
if (ch == ' ')
{
spaces++;
}
} while (ch != '.');
Console.WriteLine("Number of spaces counted = {0}", spaces);
Console.ReadKey();
}
}
However I think the program becomes more interesting if you update it to the following:
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("Enter characters,finish with a period (\".\"");
char ch;
int spaces = 0;
do
{
ch = (char)Console.Read();
if (ch == ' ')
{
spaces++;
}
} while (ch != '.');
Console.WriteLine("Number of spaces counted = {0}", spaces);
}
}
}
My example uses Console.ReadKey instead of Console.Read:
class Program
{
static void Main(string[] args)
{
int spaces = 0;
char key;
while ((key = Console.ReadKey().KeyChar) != '.') {
if (key == ' ')
spaces++;
}
Console.WriteLine();
Console.WriteLine("Number of spaces: {0}", spaces);
Console.ReadKey();
}
}
If we create a helper method that creates a sequence of keys from the console:
public static IEnumerable<char> ReadKeys()
{
while (true)
{
yield return Console.ReadKey().KeyChar;
}
}
It allows us to write a query describing exactly what you want:
var spaces = ReadKeys()
.TakeWhile(c => c != '.')
.Count(c => c == ' ');
Take characters until you get a period, and count the number of spaces.
Use Console.ReadKey() to get ConsoleKeyInfo. Then verify pressed Key. You don't need to work with characters:
int spaces = 0;
ConsoleKey key;
do
{
key = Console.ReadKey().Key;
if (key == ConsoleKey.Spacebar)
spaces++;
}
while (key != ConsoleKey.OemPeriod);
Console.WriteLine("Number of spaces counted = {0}",spaces);
Keep in mind that period key on NumPad has value ConsoleKey.Decimal. So, if you need to handle both period keys, you should write following condition:
while (key != ConsoleKey.OemPeriod && key != ConsoleKey.Decimal);

Categories

Resources