6

I'm still a beginner to programming in high-level programming languages, so I don't know if this is an easy solution, but I'm happy to learn anyway. I've programmed a little alarm program in C# that let's the user input in how many seconds the alarm needs to go off. It works perfectly, but the input that the user needs to give has to be a number. When the user inputs any form of text, the program crashes. Now, how can I prevent that users input text, and call a function or do something else when the user does, instead of the program just crashing?

This is the code I have now:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test
{
    class Alarm
    {
        public static void play()
        {
            int sec;
            sec = Convert.ToInt16(Console.ReadLine());

            for (int i = 0; i < seconds; ++i)
            {
                System.Threading.Thread.Sleep(1000);
            }

            for (int i = 0; i < 10; i++)
            {
                Console.Beep();
            }
        }
    }
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
DutchLearner
  • 335
  • 3
  • 13
  • Well, off the top of my head, you could use a `try` `catch` around the convert and handle the exception however you like, for example ask them to re-enter a value. – user17753 Jun 27 '12 at 13:18
  • 3
    On a seperate note, `int` is a `Int32` not a `Int16`. `short` is the alias for `Int16` – Scott Chamberlain Jun 27 '12 at 13:19
  • @JustinPihony I didn't even know about that. I accepted all the answers from the past that helped me. Thanks for the tip. :) – DutchLearner Jun 27 '12 at 13:38

8 Answers8

11

You should complete a check before converting:

int sec;

if (int.TryParse(Console.ReadLine(), out sec)
{
  // this is valid continue
}
else
{
  // show error highlighting that entry must be a number
}

int.TryParse will return a boolean highlighting whether the input is parsable to an int. It will also set your sec variable to the value if successful.

Lloyd Powell
  • 18,270
  • 17
  • 87
  • 123
  • That worked, thanks a bunch! I only needed to put it all in a while loop and make a Boolean value that evaluated whether the function could finish or not, and that was it. :D – DutchLearner Jun 27 '12 at 13:34
7

You could loop indefinitely until the user inputs a number:

int number = 0;
while(!Int32.TryParse(Console.ReadLine(), out number))
{
    Console.WriteLine("Please input a number.");
}

Int32.TryParse returns false if the conversion failed, instead of throwing an exception and if successful returns the result in the second out parameter.

Tudor
  • 61,523
  • 12
  • 102
  • 142
1

You should use a try parse method.

Something like this:

  int number;
  bool result = Int32.TryParse(Console.ReadLine(), out number);

If result is true, then it has successfully parsed it, which means it is an integer. If not, it has failed, which means it isn't an integer.

You can then use number as the value that was parsed out as your int32.

Blueberry
  • 2,211
  • 3
  • 19
  • 33
1

Already people answered here. I love to make that as an extension method so that i can call it in so many places.

public static bool IsNumeric(this string theValue)
{
  long retNum;
  return long.TryParse(theValue, System.Globalization.NumberStyles.Integer, 
            System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
}

Then I will call it like this

if(Console.ReadLine().IsNumeric())
{
    //The value is numeric. You can use it    
}
Shyju
  • 214,206
  • 104
  • 411
  • 497
0

replace

sec = Convert.ToInt16(Console.ReadLine());

with

try {
    sec = Convert.ToInt16(Console.ReadLine());
}

catch(Exception e ){
    Console.Writeline(" Enter numbers only");
}
madhairsilence
  • 3,787
  • 2
  • 35
  • 76
0

What you are trying to do is often called Input Validation. In your case you need to check that they entered a number before parsing it. Int16 has a TryParse function that will help you out.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
0

Adding a separate function that uses a try statement to catch the error that is produce when your try to covert an invalid string to an integer.

int readInput()
{
    int sec;
    while(true)
    {
        try
        {
            sec = Convert.ToInt16(Console.ReadLine());
            return sec;
        }
        catch(Exception e) 
                    { 
                            Console.WriteLine("Enter an integer!");
                    }
    }
    return 0;
}
  • You dont want to do this... Exception handling to form part of control flow is similar to using non-local goto statements all over your code. – Blueberry Jun 27 '12 at 13:27
0

If you want to do something more elegant than displaying an error message and asking for the user to reenter data, you could try processing each keystroke as it happens with Console.Readkey() and rejecting them if the would result in a string that isn't a number.

I did something like this years ago in TurboPascal.

This is pseudocode written from memory but should get you on the right path. If you need to take floating point values as well as integers, or both negative and positive numbers you'll need to add more logic to handle those cases.

string enteredText = "";
char key;
bool done = false;
while (!done) 
{
   key = Console.ReadKey();
   if (key is number)
       enteredText += key;
   else if (key is backspace)
   {
       //remove the last char from enteredText.  Handle case where enteredText has length 0
       Console.Write(backspace); 
   }
   else if ((key is enter) && (enteredText.Length > 0))
       done = true;
   else
   {
       // invalid char.
       //MSDN says the char is echoed to the console so remove it
       Console.Write(backspace);
       //Beep at the user?
   }
}