Ryan W
Ryan W

Reputation: 39

C# How to make repeated input overlap?

When the input's type is not an integer, the program should fail. However, there are two problems:

  1. After a letter is typed and I get the "not valid" response, then if the next input is a number, it won't accept it and says "not valid".
  2. How can I make it so when a wrong number is inputted, it stays on the same row and just clears the previous input from the screen (and allows for a retry from the same position)?

    static void Main(string[] args)
    {
        int firstNum;
        int Operation = 1;
    
        switch (Operation)
        {
            case 1:
                Console.SetCursorPosition(0, 0);
                Console.Write("Write a number: ");
                firstNum = ReadInteger("");
                Console.ReadKey();
                break;
        }
    }
    
    private static int ReadInteger(string title)
    {
        while (true)
        {
            if (!string.IsNullOrWhiteSpace(title))
                Console.WriteLine(title);
    
            string input = Console.ReadLine();
    
            if (int.TryParse(input, out int result))
                return result;
    
            Console.WriteLine("Sorry, not a valid integer value; please, try again.");
            Console.ReadKey();
        }
    }
    

Upvotes: 2

Views: 195

Answers (2)

Markus Safar
Markus Safar

Reputation: 6580

Ad 1)

Because you have Console.ReadKey at the end of ReadInteger which will be executed as well. So if you hit Console.ReadLine at the line string input = Console.ReadLine(); and enter something that is not a number, int.TryParse will return false. This leads to the error message and the execution of Console.ReadKey. So you should first of all get rid of that Console.ReadKey there.


Ad 2)

You are setting the cursor position before the call of ReadInteger but not within ReadInteger. So if someone enters a text, the end of the input is typically done by pressing enter. You then write a line (with Console.WriteLine). So if you want to have the cursor at the same position, you will have to reset it's position within the loop which is within the ReadInteger method.

Upvotes: 2

Flydog57
Flydog57

Reputation: 7111

How about something like this:

 public static int ReadInt(string prompt)
 {
     Console.Clear();
     var length = prompt.Length + 2;     //2 is for a colon and a space
     var position = length;
     Console.Write($"{prompt}: ");
     string buffer = String.Empty;
     int returnNum = 0;
     while (true)
     {
         Console.SetCursorPosition(position, 0);
         var charRead = Console.ReadKey();
         if(charRead.KeyChar == '\r')
         {
             return returnNum;
         }
         if (!int.TryParse(buffer + charRead.KeyChar, out returnNum))
         {
             Console.SetCursorPosition(position, 0);
             Console.WriteLine(" "); //overwrite
             Console.SetCursorPosition(0, 1);
             Console.Write("Error: enter only digits");
             continue;
         }
         else
         {
             buffer += charRead.KeyChar;
             ++position;
             //overwrite any error
             Console.SetCursorPosition(0, 1);
             Console.Write("                         ");
         }
     }
 }

It's not perfect. It doesn't handle typing in too many digits. It doesn't handle backspace. It clears the console to establish position (it doesn't look like you can read the console position, and I'm too lazy to keep track of things).

If you do handle backspace, make sure you don't let users backup too much. It's been years (um, no, decades) since I've done low level console management, but I can remember doing this in CP/M in the early 80s - if you backed up to far, the OS died (which would be a very result in Windows :-) ).

Upvotes: -1

Related Questions