I have written my codes and i want to validate it in such a way thet it will only allow intergers to be inputed and not alphabets. Here is the code, please I will love you to help me. Thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace minimum
{
class Program
{
static void Main(string[] args)
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int c = Convert.ToInt32(Console.ReadLine());
if (a < b)
{
if (a < c)
{
Console.WriteLine(a + "is the minimum number");
}
}
if (b < a)
{
if (b < c)
{
Console.WriteLine(b + "is the minimum number");
}
}
if (c < a)
{
if (c < b)
{
Console.WriteLine(c + "is the minimum number");
}
}
Console.ReadLine();
}
}
}
You should test if it's an int instead of converting in right away.
Try something like :
string line = Console.ReadLine();
int value;
if (int.TryParse(line, out value))
{
// this is an int
// do you minimum number check here
}
else
{
// this is not an int
}
Simply call Readline() and loop with Int.TryParse until the user inputs a valid number :)
int X;
String Result = Console.ReadLine();
while(!Int32.TryParse(Result, out X))
{
Console.WriteLine("Not a valid number, try again.");
Result = Console.ReadLine();
}
Hope that helps
To get the console to filter out alphabetical keystrokes you have to take over input parsing. The Console.ReadKey() method is fundamental to this, it lets you sniff the pressed key. Here's a sample implementation:
static string ReadNumber() {
var buf = new StringBuilder();
for (; ; ) {
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter && buf.Length > 0) {
return buf.ToString() ;
}
else if (key.Key == ConsoleKey.Backspace && buf.Length > 0) {
buf.Remove(buf.Length-1, 1);
Console.Write("\b \b");
}
else if ("0123456789.-".Contains(key.KeyChar)) {
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else {
Console.Beep();
}
}
}
You could add, say, Decimal.TryParse() in the if() statement that detects the Enter key to verify that the entered string is still a valid number. That way you can reject input like "1-2".
Do not Convert the input from the user immediately. Put it in a string and use Int32.TryParse(...) to find out whether or not a number was entered. Like this:
int i;
string input = Console.ReadLine();
if(Int32.TryParse(input, out i))
{
// it is a number and it is stored in i
}
else
{
// it is not a number
}
Note that
if (a < b) {
if (a < c) {
is equivalent to
if (a < b && a < c) {
and that this latter form introduces less nesting and is more readable, particularly if your code grows more complex. Also, you should probably never use Convert.ToInt32 - it has a particularly ill-conceived and surprising corner case; and it's also less type-safe than int.Parse which is the superior choice where possible - or int.TryParse when you're unsure whether the string is valid. Basically, avoid Convert.... wherever possible.
string Temp;
int tempInt,a;
bool result=false;
while ( result == false )
{
Console.Write ("\n Enter A Number : ");
Temp = Console.ReadLine ();
result = int.TryParse (Temp, out tempInt);
if ( result == false )
{
Console.Write ("\n Please Enter Numbers Only.");
}
else
{
a=tempInt;
break;
}
}
My preferred solution would be:
static void Main()
{
Console.WriteLine(
(
from line in Generate(()=>Console.ReadLine()).Take(3)
let val = ParseAsInt(line)
where val.HasValue
select val.Value
).Min()
);
}
static IEnumerable<T> Generate<T>(Func<T> generator) {
while(true) yield return generator();
}
static int? ParseAsInt(string str) {
int retval;
return int.TryParse(str,out retval) ? retval : default(int?);
}
Of course, depending on the specification (should invalid number be retried?), it may need to be tweaked.
Double/Float:
I'm just extending #Hans Passant answer (Taking care of DecimalSeparator and "-"):
static double ReadNumber()
{
var buf = new StringBuilder();
for (; ; )
{
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter && buf.Length > 0)
{
Console.WriteLine();
return Convert.ToDouble(buf.ToString());
}
else if (key.Key == ConsoleKey.Backspace && buf.Length > 0)
{
buf.Remove(buf.Length - 1, 1);
Console.Write("\b \b");
}
else if (System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator.Contains(key.KeyChar) && buf.ToString().IndexOf(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) == -1)
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else if ("-".Contains(key.KeyChar) && buf.ToString().IndexOf("-") == -1 && buf.ToString() == "")
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else if ("0123456789".Contains(key.KeyChar))
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else
{
Console.Beep();
}
}
}
var getInput=Console.ReadLine();
int option;
//validating input
while(!int.TryParse(getInput, out option))
{
Console.WriteLine("Incorrect input type. Please try again");
getInput=Console.ReadLine();
}
Try This Simple
try
{
string x= "aaa";
Convert.ToInt16(x);
//if success is integer not go to catch
}
catch
{
//if not integer
return;
}
Related
So I have this code that will calculate the arithmetic mean. The user has to introduce random numbers, and when the input is "x" the code will stop and calculate the arithmetic mean. The code works fine if I introduce any numbers. However, if the first input is "x" I have to display "0". In the console, I get null ("") instead of 0.
The problem is the 'else' condition, the rest of the code works as expected. I tried to write the condition in different ways and even to put it in another block because I thought it is unreachable, but it is still null. I am not sure what I am missing.
Thank you in advance!
string line = Console.ReadLine();
double sum = 0;
double count = 0;
while (line != "x")
{
double number = Convert.ToInt32(line);
sum += number;
count++;
line = Console.ReadLine();
if (line == "x")
{
if (count > 0)
{
double ma = sum / count;
Console.WriteLine((float)ma);
}
else {
Console.WriteLine(0);
}
}
}
This worked for me. It wasn't clear what to do if user enters something other than 'x' or a number, so I put some error handling which ensures the app doesn't crash. I added a flag to detect if at least one valid number has been entered.
static void Main(string[] args)
{
string line = Console.ReadLine();
double sum = 0;
double count = 0;
bool numberHasBeenEntered = false;
while (line != "x")
{
double number;
//some error handling in case user enters something other than x or a number
try
{
number = Convert.ToInt32(line);
numberHasBeenEntered = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
sum += number;
count++;
line = Console.ReadLine();
if (line == "x")
{
if (count > 0)
{
double ma = sum / count;
Console.WriteLine((float)ma);
}
else
{
Console.WriteLine(0);
}
}
}
if (numberHasBeenEntered == false) Console.WriteLine(0);
}
If your first line is "X" then the code inside the while loop is not executed at all.
Use a do While loop
string line = Console.ReadLine();
double sum = 0;
double count = 0;
double number;
double ma;
do
{
if (line == "x")
{
if (count > 0)
{
line = Console.ReadLine();
ma = sum / count;
Console.WriteLine((float)ma);
}
else {
Console.WriteLine("0");
}
}
else
{
number = Convert.ToInt32(line);
sum += number;
count++;
}
}
while(line != "x")
I'm writing a function to test if a string is a palindrome or not and I am wondering how to return the middle letter or letters if the string is indeed a palindrome?
Here's what i have so far:
My bool to check if the string is a palindrome:
public static bool IsPalindrome(string input)
{
int i = 0;
int j = input.Length - 1;
while (true)
{
if (i > j)
{
return true;
}
char a = input[i];
char b = input[j];
if (!a.Equals(b))
{
return false;
}
i++;
j--;
}
}
And here is where I'd like to be able to print out the middle letter(s):
while (true)
{
Console.Clear();
Regex myRegex = new Regex("[ ;:,.-?'!\"]");
string userInput = String.Empty;
Console.WriteLine("Please enter sentence or phrase");
userInput = Console.ReadLine();
Console.WriteLine();
if (IsPalindrome(myRegex.Replace(userInput, string.Empty).ToLower()))
{
Console.WriteLine("True");
Console.WriteLine("Press any key to continue");
}
else
{
Console.WriteLine("False");
Console.WriteLine("Press any key to continue");
}
Console.ReadLine();
}
Here's another implementation to return the middle letter(s):
public string MiddleLettersOf(string s)
{
if (s.Length == 0)
return "";
if ((s.Length & 1) == 1) // Odd length?
return s.Substring(s.Length/2, 1);
return s.Substring(s.Length/2-1, 2);
}
(This assumes that passing a null string is an error and therefore I allow it to throw a NullReferenceException.)
By the way, a simple (but not the most efficient) way of checking a string to see if it's a palindrome is:
public static bool IsPalindrome(string s)
{
return s.SequenceEqual(s.Reverse());
}
You can generalise that test to any IEnumerable:
public static bool IsPalindrome<T>(IEnumerable<T> s)
{
return s.SequenceEqual(s.Reverse());
}
but the flaw with that code is that s is enumerated twice, which might be A Bad Thing.
Try this:
private static string GetMiddleLetters(string input)
{
//Find the middle point
var mid = input.Length / 2.0;
//If it's odd, we take 1 letter, if it's even, we take 2
var numToTake = (mid == (int)mid) ? 2 : 1;
//Round up from the middle, and subtract one (as Substring is 0-indexed)
var startIndex = (int)Math.Ceiling(mid) - 1;
return input.Substring((int)Math.Ceiling(mid) - 1, numToTake);
}
And use it like this:
var fixedString = myRegex.Replace(userInput, string.Empty).ToLower();
if (IsPalindrome(fixedString))
{
Console.WriteLine(GetMiddleLetters(fixedString));
//Rest of the code here...
}
Something like that:
public static String MiddleLetters(string value) {
if (String.IsNullOrEmpty(value))
return value; // middle of the "null" is supposed to be null
return value.Length % 2 == 0 ?
value.Substring(value.Length / 2 - 1, 2)
: value.Substring(value.Length / 2, 1);
}
To test for being palindrome:
public static bool IsPalindrome(string value) {
if (String.IsNullOrEmpty(value))
return true; // or false, or throw an exception
//TODO: are you looking for case sensitive or case insensitive palindromes?
for (int i = 0; i < value.Length / 2; ++i)
if (value[i] != value[value.Length - i - 1])
return false;
return true;
}
Console.WriteLine("Enter the cost of the item");
string input = Console.ReadLine();
double price = Convert.ToDouble(input);
Hello, I want the keyboard buttons, A-Z, brackets, question mark, etc to be disabled. I want it so if you type it in, it will not show up in the Console. I only want the numbers 1-9 to show up. This is in C# Console application. Thanks for the help!
try this code snippet
string _val = "";
Console.Write("Enter your value: ");
ConsoleKeyInfo key;
do
{
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace)
{
double val = 0;
bool _x = double.TryParse(key.KeyChar.ToString(), out val);
if (_x)
{
_val += key.KeyChar;
Console.Write(key.KeyChar);
}
}
else
{
if (key.Key == ConsoleKey.Backspace && _val.Length > 0)
{
_val = _val.Substring(0, (_val.Length - 1));
Console.Write("\b \b");
}
}
}
// Stops Receving Keys Once Enter is Pressed
while (key.Key != ConsoleKey.Enter);
Console.WriteLine();
Console.WriteLine("The Value You entered is : " + _val);
Console.ReadKey();
This MSDN article explains how to read characters one at a time in a console window. Test each character as it is input with the Char.IsNumber() method, and reject those characters that fail the test.
In a while, I got a solution really short:
double number;
Console.Write("Enter the cost of the item: ");
while (!double.TryParse(Console.ReadLine(), out number))
{
Console.Write("This is not valid input. Please enter an integer value: ");
}
Console.Write("The item cost is: {0}", number);
See you!
Here is one approach. It's probably overkill if you're just starting out in C#, since it uses some more advanced aspects of the language. In any case, I hope you find it interesting.
It has some nice features:
The ReadKeys method takes an arbitrary function for testing whether the string so far is valid. This makes it easy to reuse whenever you want filtered input from the keyboard (e.g. letters or numbers but no punctuation).
It should handle anything you throw at it that can be interpreted as a double, e.g. "-123.4E77".
However, unlike John Woo's answer it doesn't handle backspaces.
Here is the code:
using System;
public static class ConsoleExtensions
{
public static void Main()
{
string entry = ConsoleExtensions.ReadKeys(
s => { StringToDouble(s) /* might throw */; return true; });
double result = StringToDouble(entry);
Console.WriteLine();
Console.WriteLine("Result was {0}", result);
}
public static double StringToDouble(string s)
{
try
{
return double.Parse(s);
}
catch (FormatException)
{
// handle trailing E and +/- signs
return double.Parse(s + '0');
}
// anything else will be thrown as an exception
}
public static string ReadKeys(Predicate<string> check)
{
string valid = string.Empty;
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
return valid;
}
bool isValid = false;
char keyChar = key.KeyChar;
string candidate = valid + keyChar;
try
{
isValid = check(candidate);
}
catch (Exception)
{
// if this raises any sort of exception then the key wasn't valid
// one of the rare cases when catching Exception is reasonable
// (since we really don't care what type it was)
}
if (isValid)
{
Console.Write(keyChar);
valid = candidate;
}
}
}
}
You also could implement an IsStringOrDouble function that returns false instead of throwing an exception, but I leave that as an exercise.
Another way this could be extended would be for ReadKeys to take two Predicate<string> parameters: one to determine whether the substring represented the start of a valid entry and one the second to say whether it was complete. In that way we could allow keypresses to contribute, but disallow the Enter key until entry was complete. This would be useful for things like password entry where you want to ensure a certain strength, or for "yes"/"no" entry.
This code will allow you to:
Write only one dot (because numbers can have only one decimal separator);
One minus at the begining;
One zero at the begining.
It means that you not be able to write something like: "00000.5" or "0000...-5".
class Program
{
static string backValue = "";
static double value;
static ConsoleKeyInfo inputKey;
static void Main(string[] args)
{
Console.Title = "";
Console.Write("Enter your value: ");
do
{
inputKey = Console.ReadKey(true);
if (char.IsDigit(inputKey.KeyChar))
{
if (inputKey.KeyChar == '0')
{
if (!backValue.StartsWith("0") || backValue.Contains('.'))
Write();
}
else
Write();
}
if (inputKey.KeyChar == '-' && backValue.Length == 0 ||
inputKey.KeyChar == '.' && !backValue.Contains(inputKey.KeyChar) &&
backValue.Length > 0)
Write();
if (inputKey.Key == ConsoleKey.Backspace && backValue.Length > 0)
{
backValue = backValue.Substring(0, backValue.Length - 1);
Console.Write("\b \b");
}
} while (inputKey.Key != ConsoleKey.Enter); //Loop until Enter key not pressed
if (double.TryParse(backValue, out value))
Console.Write("\n{0}^2 = {1}", value, Math.Pow(value, 2));
Console.ReadKey();
}
static void Write()
{
backValue += inputKey.KeyChar;
Console.Write(inputKey.KeyChar);
}
}
You can do it with a single line code as follows:
int n;
Console.WriteLine("Enter a number: ");
while (!int.TryParse(Console.ReadLine(), out n)) Console.WriteLine("Integers only allowed."); // This line will do the trick
Console.WriteLine($"The number is {n}");
You can change int into double in case you wanted to allow double instead of integers and so on.
string input;
double price;
bool result = false;
while ( result == false )
{
Console.Write ("\n Enter the cost of the item : ");
input = Console.ReadLine ();
result = double.TryParse (input, out price);
if ( result == false )
{
Console.Write ("\n Please Enter Numbers Only.");
}
else
{
Console.Write ("\n cost of the item : {0} \n ", price);
break;
}
}
I need to press t two times in order to get any output; otherwise the program goes directly into the else condition or gives an exception handler error. What am I doing wrong here?
As you guys can see there are two classes one twotable and other program which contains the main method. I am trying to get the output using the invoke method of twotable class.
namespace ConsoleApplication6
{
class twotable
{
public static void two()
{
int i;
int j;
for (i = 1; i <= 10;i++)
{
for (j = 2; j <= 2;j++ )
{
Console.WriteLine(i * j);
}
}
}
}
class Program
{
static void Main()
{
Console.WriteLine("Press t for two table");
char c = Convert.ToChar(Console.ReadLine());
{
char t = Convert.ToChar(Console.ReadLine());
if (c == t)
{
twotable.two();
}
else
{
Console.WriteLine("i hate u");
}
}
}
}
}
You are reading from the console twice.
Instead of
char t = Convert.ToChar(Console.ReadLine());
if (c == t)
You need
if (c == 't')
Do you want the user to enter in the character 't' twice on separate ReadLine()s in order to show the output? If so:
static void Main()
{
Console.WriteLine("Press t for two table");
char c1 = Convert.ToChar(Console.ReadLine());
char c2 = Convert.ToChar(Console.ReadLine());
if (c1 == 't' && c2 == 't')
{
twotable.two();
}
else
{
Console.WriteLine("i hate u");
}
}
Or do you want to read in 'tt' in one ReadLine()?
static void Main()
{
Console.WriteLine("Press t for two table");
string input = Console.ReadLine();
if (input.Equals("tt"))
{
twotable.two();
}
else
{
Console.WriteLine("i hate u");
}
}
Code is little bit messy, but loking even on this code
char c = Convert.ToChar(Console.ReadLine());
...
{
char t = Convert.ToChar(Console.ReadLine());
.....
}
you call Console.ReadLine(...) 2 times, so you need to press t 2 times.
It's hard to say, but probabbly you want to do something like:
char t = 't';
...
{
char consoleChar = Convert.ToChar(Console.ReadLine());
if(consoleChar == t) // or simple if(consoleChar == 't')
{
//do something here, we get a t symbol from console
}
.....
}
My be need to use Console.ReadKey instead, and test c == 't':
Obtains the next character or function key pressed by the user.
and your code like this:
var cki = Console.ReadKey();
if (cki.KeyChar == 't')
{
...
}
I think your problem is here - char c. You're comparing char c with char t
Both lines ask for user input.
char c = Convert.ToChar(Console.ReadLine());
Is there any way to detect both Readline and ReadKey, so that in most cases it behaves as a readline, except for some special key inputs that should be detected?
I need some "parallel" implementation to introduce simultaneity.
The code below is synchronous and does not meet my need
while ((line = Console.ReadLine()) != "x")
{
if (line == "BLABLA")
{
//Stuff
}
else
{
//Stuff
}
ConsoleKeyInfo ki = Console.ReadKey(true);
if ((ki.Key == ConsoleKey.V) && (ki.Modifiers == ConsoleModifiers.Control))
{
//Stuff
}
}
Here's a function I just made to do this.
Right now it only handles Backspace, Enter and Esc, but it could easily be modified to handle other keys if you deem them necessary.
// returns null if user pressed Escape, or the contents of the line if they pressed Enter.
private static string ReadLineOrEsc()
{
string retString = "";
int curIndex = 0;
do
{
ConsoleKeyInfo readKeyResult = Console.ReadKey(true);
// handle Esc
if (readKeyResult.Key == ConsoleKey.Escape)
{
Console.WriteLine();
return null;
}
// handle Enter
if (readKeyResult.Key == ConsoleKey.Enter)
{
Console.WriteLine();
return retString;
}
// handle backspace
if (readKeyResult.Key == ConsoleKey.Backspace)
{
if (curIndex > 0)
{
retString = retString.Remove(retString.Length - 1);
Console.Write(readKeyResult.KeyChar);
Console.Write(' ');
Console.Write(readKeyResult.KeyChar);
curIndex--;
}
}
else
// handle all other keypresses
{
retString += readKeyResult.KeyChar;
Console.Write(readKeyResult.KeyChar);
curIndex++;
}
}
while (true);
}
No, not as such. Both methods block until the user enters something on the console. So even if you would find a way to have both run in parallel, it will not be deterministic which one gets the first shot.
There is a (not obvious) similar problem: how to make Console.ReadLine() abort/break after a certain amount of time without user input.
There have been multiple attempts for this problem here:
Console.ReadLine Break
How to add a Timeout to Console.ReadLine()?
Most are modelled around either creating your own version of a ReadLine function that adds a timeout (or in your case special handling for certain character (codes)) or the use some sort of threading.
Both ways are either non-trivial or have their own issues (make sure you review the comments, even for the accepted answers).
In short, I think you will need to roll your own version of ReadLine, based on Console.ReadKey with your special handling included and that much of the genuine Console.ReadLine behavior that you require. Note that this even include such basic things as RETURN, ARROW KEYS, BACKSPACE handling, etc.
Update: There is the getline.cs Code from the Mono project, which implements a line editing capability like it was provided by some venerable UNIX shells (EMACS mode, if you care). For that, I believe it will need to implement some sort of ReadLine replacement, although I haven't checked. Maybe you can use this as a starting point.
Here is a method that I created that works great. You do not have to press button twice in order for string to start appearing. Basically this replaces Console.ReadLine() but it also looks for Esc key pressed. Just look at return type of method if it is null then you know Esc was pressed.
private string ReadLineOrEscape()
{
ConsoleKeyInfo keyInfo = new ConsoleKeyInfo();
StringBuilder sb = new StringBuilder();
int index = 0;
while (keyInfo.Key != ConsoleKey.Enter)
{
keyInfo = Console.ReadKey(true);
if (keyInfo.Key == ConsoleKey.Escape)
{
return null;
}
if(keyInfo.Key == ConsoleKey.Backspace)
{
if (index > 0)
{
Console.CursorLeft = index - 1;
sb.Remove(index - 1, 1);
Console.Write(" \b");
index--;
}
}
if(keyInfo.KeyChar > 31 && keyInfo.KeyChar < 127)
{
index++;
Console.Write(keyInfo.KeyChar);
sb.Append(keyInfo.KeyChar);
}
}
return sb.ToString(); ;
}
In response to #Overlord Zurd, I improved the code provided by the user.
public class ConsoleOutput
{
private ConsoleOutputType OutputType { get; set; }
private object MyObject { get; }
private static bool IsInserting { get; set; }
public string KeyName => IsKey() && (ConsoleKeyInfo)MyObject != null ? ((ConsoleKeyInfo)MyObject).Key.ToString() : "Null";
public string OutputString => !IsKey() && MyObject != null ? (string)MyObject : string.Empty;
public static event Action<string> ReadInput = delegate { };
public static event Action<ConsoleKeyInfo> ReadKey = delegate { };
private ConsoleOutput()
{
}
public ConsoleOutput(object obj)
{
MyObject = obj;
OutputType = obj is ConsoleKeyInfo ? ConsoleOutputType.Key : ConsoleOutputType.Value;
}
public bool IsKey()
{
return OutputType == ConsoleOutputType.Key;
}
public bool IsExitKey()
{
if (!IsKey())
return false;
var info = ((ConsoleKeyInfo)MyObject);
return (info.Modifiers & ConsoleModifiers.Control) != 0 && info.Key == ConsoleKey.B;
}
public string GetValue()
{
return (string)MyObject;
}
// returns null if user pressed Escape, or the contents of the line if they pressed Enter.
public static ConsoleOutput ReadLineOrKey()
{
string retString = "";
int curIndex = 0;
do
{
ConsoleKeyInfo readKeyResult = Console.ReadKey(true);
// handle Enter
if (readKeyResult.Key == ConsoleKey.Enter)
{
ReadInput?.Invoke(retString);
Console.WriteLine();
return new ConsoleOutput(retString);
}
// handle backspace
if (readKeyResult.Key == ConsoleKey.Backspace)
{
if (curIndex > 0)
{
retString = retString.Remove(retString.Length - 1);
Console.Write(readKeyResult.KeyChar);
Console.Write(' ');
Console.Write(readKeyResult.KeyChar);
--curIndex;
}
}
else if (readKeyResult.Key == ConsoleKey.Delete)
{
if (retString.Length - curIndex > 0)
{
// Store current position
int curLeftPos = Console.CursorLeft;
// Redraw string
for (int i = curIndex + 1; i < retString.Length; ++i)
Console.Write(retString[i]);
// Remove last repeated char
Console.Write(' ');
// Restore position
Console.SetCursorPosition(curLeftPos, Console.CursorTop);
// Remove string
retString = retString.Remove(curIndex, 1);
}
}
else if (readKeyResult.Key == ConsoleKey.RightArrow)
{
if (curIndex < retString.Length)
{
++Console.CursorLeft;
++curIndex;
}
}
else if (readKeyResult.Key == ConsoleKey.LeftArrow)
{
if (curIndex > 0)
{
--Console.CursorLeft;
--curIndex;
}
}
else if (readKeyResult.Key == ConsoleKey.Insert)
{
IsInserting = !IsInserting;
}
#if DEBUG
else if (readKeyResult.Key == ConsoleKey.UpArrow)
{
if (Console.CursorTop > 0)
--Console.CursorTop;
}
else if (readKeyResult.Key == ConsoleKey.DownArrow)
{
if (Console.CursorTop < Console.BufferHeight - 1)
++Console.CursorTop;
}
#endif
else
// handle all other keypresses
{
if (IsInserting || curIndex == retString.Length)
{
retString += readKeyResult.KeyChar;
Console.Write(readKeyResult.KeyChar);
++curIndex;
}
else
{
// Store char
char c = readKeyResult.KeyChar;
// Write char at position
Console.Write(c);
// Store cursor position
int curLeftPos = Console.CursorLeft;
// Clear console from curIndex to end
for (int i = curIndex; i < retString.Length; ++i)
Console.Write(' ');
// Go back
Console.SetCursorPosition(curLeftPos, Console.CursorTop);
// Write the chars from curIndex to end (with the new appended char)
for (int i = curIndex; i < retString.Length; ++i)
Console.Write(retString[i]);
// Restore again
Console.SetCursorPosition(curLeftPos, Console.CursorTop);
// Store in the string
retString = retString.Insert(curIndex, new string(c, 1));
// Sum one to the cur index (we appended one char)
++curIndex;
}
}
if (char.IsControl(readKeyResult.KeyChar) &&
readKeyResult.Key != ConsoleKey.Enter &&
readKeyResult.Key != ConsoleKey.Backspace &&
readKeyResult.Key != ConsoleKey.Tab &&
readKeyResult.Key != ConsoleKey.Delete &&
readKeyResult.Key != ConsoleKey.RightArrow &&
readKeyResult.Key != ConsoleKey.LeftArrow &&
readKeyResult.Key != ConsoleKey.Insert)
{
#if DEBUG
if (readKeyResult.Key == ConsoleKey.UpArrow || readKeyResult.Key == ConsoleKey.DownArrow)
continue;
#endif
ReadKey?.Invoke(readKeyResult);
Console.WriteLine();
return new ConsoleOutput(readKeyResult);
}
}
while (true);
}
}
As you can see, I implemented Insert, Arrow control, Delete, etc etc... (Insert was an important thing because if you write any text with this code you will see behavior as Insert key provides).
And example of use:
internal class Program
{
private static void Main(string[] args)
{
Console.Write("Write test string: ");
var test = ConsoleOutput.ReadLineOrKey();
if (test.IsKey())
Console.WriteLine(test.KeyName);
else
Console.WriteLine($"Output string: {test.OutputString}");
Console.Read();
}
}
You can keep updated on this link (is a link to my lib I'm currently working at).