-2

I am writing a small console application in C# and it requires two numeric parameters/arguments to be passed to it. I am checking for no params, more than 2 params, if two params. I am also converting those params if 2 returned to numeric for calculations I'm doing. One thing I'm not doing is verifying what's being passed is a number so assume program will crap out if I pass a letter. Is there a look routing I can just run to verify the params passed are in deed able to be numbers? I can handle the kick out from there but curious how you check if an argument CAN be a number or not.

Thanks.

JR

John
  • 61
  • 2
  • 7

3 Answers3

2

I would simplify this task as follows:

Create custom Convert method:

static double Convert(string s)
{
    double result;
    if (!double.TryParse(s, out result))
        result = double.NaN;
    return result;
}

Use it in Main:

static void Main(string[] args)
{
    var doubles = args.Select(a => Convert(a)).ToArray();
    var valid = doubles.All(a => !double.IsNaN(a));
}
Paweł Dyl
  • 8,888
  • 1
  • 11
  • 27
1

Here's one way;

static void Main(string[] args)
    {
        foreach (var arg in args)
        {
            int asInt;
            // Returns "true" if arg can be parsed as an int and false otherwise;
            // If you want to allow doubles you can also try double.TryParse in a similar manner
            if (int.TryParse(arg, out asInt))
            {
                // Handle
            }
            // Failed to parse argument as an int
            else
            {
                throw new ArgumentException("arg not an int");
            }
        }
 }

You could also use a Regex:

    static void Main(string[] args)
    {
        // Make sure this can is either an int or a double
        var regex = new Regex(@"^-?(([0-9]+)|([0-9]+\.[0-9]+(e[0-9]+)?))$");

        foreach (var arg in args)
        {
            if (!regex.IsMatch(arg))
                throw new ArgumentException("arg " + arg + " is not an int or double");
        }
    }

Note a few important features of this regex:
- The "@" literal symbol in front of the regex string
- The ^ and $ to mark the beginning and end of lines - i.e. the string must contain only a number or only a double
- This bans empty strings as well
Edit: I edited the Regex to optionally allow for something like "1.0e100" or "-123", which, as pointed out in the comments, are also perfectly valid ints and doubles. Also, as pointed out in the comments, it's probably better to use int.TryParse or double.TryParse rather than reinventing the wheel.

  • 4
    I doubt if using *regular expression* is a good way here. On one hand, I can't put `1.0e100` (pretty *legal double*) or `-123` (*legal integer*) on the other hand accepted `11...11` (*500 digits* value) is illegal. – Dmitry Bychenko Aug 15 '16 at 16:13
  • @DmitryBychenko that's perfectly true, I'll edit my post accordingly. – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:20
  • Why oh why would you use a regex to solve this when your first example is shorter, easier to read and more efficent? – Liam Aug 15 '16 at 16:25
  • @Liam yes, I agree - I edited my post to reflect the fact that the first solution's better. No point in reinventing the wheel in this case given that there's already a perfectly good library call that'll do exactly what he wants. Just added the regex as a choice because it would work (not because I think it's a good choice in this case). – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:30
  • Incidentally, can the downvoter explain why they downvoted? I think that these are perfectly legitimate solutions (the first is clearly better but the second one would still work even if it's inferior). – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:33
  • Probably because it's definitely a duplicate. Think about it, most likely this question has been asked before. P.S., there are three answers, does that put the third somewhere between "better" and "inferior"? xD – RoyalPotato Aug 15 '16 at 16:35
  • @RoyalPotato that's perfectly true, but I didn't write the question, it seems unreasonable to downvote the answer based purely on disliking the question. – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:43
  • 1
    Oh sorry, I thought you were talking about the question itself. And I agree, it is unreasonable to downvote the answer based purely on disliking the question. – RoyalPotato Aug 15 '16 at 17:05
0

There's also Char.IsDigit which always feels cleaner to me than checking for a failed parsing attempt. If you care about micro-optimizing, char.IsDigit is probably faster than parsing an invalid string too. Or, if negative numbers or non-whole numbers are your thing, you can use char.IsNumber See: https://msdn.microsoft.com/en-us/library/7f0ddtxh(v=vs.110).aspx

public static void Main(string[] args)
{
    for(int i = 0; i < args.Length; i++)
    {
        if(args[i].All((c) => char.IsDigit(c))
        {
            //It's a number.
        }
    }
}
RoyalPotato
  • 515
  • 4
  • 15
  • 1
    You'd have to loop through multi-digit numbers though, plus this wouldn't work if he wanted to accept doubles because the "." character isn't numeric – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:16
  • 2
    What if I want to put `-123`? It's a legal integer input. And `9876543210` results in *integer overflow*... Do not reinvent a wheel: `int.TryParse` is specially designed for the task. – Dmitry Bychenko Aug 15 '16 at 16:16
  • Meh, writing a function to check if a string is a valid numerical value is hardly reinventing the wheel, more like, reinventing the dustpan. But none-the-less, msdn says "TryParse is generally more efficient because it just returns false if the number is not valid." so I'm satisfied with that :) Although I don't like out parameters... – RoyalPotato Aug 15 '16 at 16:23
  • And, there's always `char.IsNumber` which **will** see '.' and negative values as numbers. – RoyalPotato Aug 15 '16 at 16:25
  • I think it's better to just use a regex or TryParse in this case - looping through the string and doing IsDigit will definitely *not* handle cases like negative numbers, doubles, or integer overflows. – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:28
  • 1
    Indeed, it won't handle overflows. Though I maintain that `char.IsNumber` return true if the character is a digit from 0-9 or a '.' or a '-'. So this solution could still be used. Besides, it's always nice to have a *different* answer when you knew that TryParse was going to be stormed into this question :). – RoyalPotato Aug 15 '16 at 16:32
  • @RoyalPotato fair point about the alternative solution – EJoshuaS - Stand with Ukraine Aug 15 '16 at 16:34
  • None-the-less, I upvoted your question. To be honest, I always use `TryParse` myself anyway, but as previously stated, I thought it'd be fun to put a different solution into the wild. – RoyalPotato Aug 15 '16 at 16:38
  • Ahem, "I upvoted your question": typo, I meant "I upvoted your answer". Oops. – RoyalPotato Aug 15 '16 at 17:06