Check whether an argument in command line is a number

K

Kuhl

Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way. I
believe there must be a better and simple way to do this check. How to
do it? BTW, I only want to treat the regular notation as a number. If
the argument is scientific notation, then I don't want to treat it as
a number. Thanks.
 
G

Guest

Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way. I
believe there must be a better and simple way to do this check. How to
do it? BTW, I only want to treat the regular notation as a number. If
the argument is scientific notation, then I don't want to treat it as
a number. Thanks.

use strtol() and check it consumes all the characters, it returns an
endptr
to indicate how much it has read
 
B

Bartc

Kuhl said:
Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way.

Actually it's not a bad way. If you need to convert the argument into a
numeric value for use in the program anyway, then use the other methods
outlined.

Otherwise checking each character of a string is '0' to '9' is not too
demanding, and allows integers of any length to be entered without worrying
about overflows. Naturally you'd put this into a function such as
isnumeric(s) returning 1 or 0.
 
L

luserXtrog

Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way.

Actually it's not a bad way. If you need to convert the argument into a
numeric value for use in the program anyway, then use the other methods
outlined.

Otherwise checking each character of a string is '0' to '9' is not too
demanding, and allows integers of any length to be entered without worrying
about overflows. Naturally you'd put this into a function such as
isnumeric(s) returning 1 or 0.

Why not use isdigit for that?
And a little loop across the string?

#include <stdio.h>

int main(void) {
char *s="12345a";

do if (!isdigit(*s)) {
printf("%c is not a digit\n", *s);
} while(*++s);

return 0;
}

hth
 
C

CBFalconer

Kuhl said:
Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say
check whether argv[3] is a number or not. I can check it by
checking and analysing each character one by one. But this is not
a good way. I believe there must be a better and simple way to do
this check. How to do it? BTW, I only want to treat the regular
notation as a number. If the argument is scientific notation,
then I don't want to treat it as a number. Thanks.

Look at the strtoul and strtoull functions. If you want to accept
negative values leave out the 'u' from the function name. At
completion, if the whole argument has been used, endptr will be
left pointing at a string terminating nul. Note that strtoull (and
strtoll) are only present under C99. After the call you have the
value converted, and a suitable validity check.
 
K

Keith Thompson

Eric Sosman said:
Perl? Ada? PL/X? Whatever the language is, it's one I don't
speak fluently.

Eric, you're about to kick yourself. It's C. Try compiling it.

I hate the code layout, though. Rather than this:

do if (condition1) {
/* ... */
} while (condition2);

I'd write:

do {
if (condition1) {
/* ... */
}
} while (condition2);

I rarely use or even see do-while loops; combining one with an if
statement that way is understandably confusing.
 
K

Keith Thompson

Eric Sosman said:
Keith said:
Eric Sosman said:
luserXtrog wrote:
Why not use isdigit for that?
And a little loop across the string?

#include <stdio.h>

int main(void) {
char *s="12345a";

do if (!isdigit(*s)) {
Perl? Ada? PL/X? Whatever the language is, it's one I don't
speak fluently.

Eric, you're about to kick yourself. [...]

You're right, as usual. (Ouch!) I mis-counted the (ouch!)
curly brac(ouch!)kets ...

For the record, it was a prediction, not a command.
 
L

luserXtrog

Keith said:
Eric Sosman said:
Keith Thompson wrote:
luserXtrog wrote:
Why not use isdigit for that?
And a little loop across the string?
#include <stdio.h>
int main(void) {
    char *s="12345a";
    do if (!isdigit(*s)) {
    Perl?  Ada?  PL/X?  Whatever the language is, it's one I don't
speak fluently.
Eric, you're about to kick yourself.  [...]
    You're right, as usual.  (Ouch!)  I mis-counted the (ouch!)
curly brac(ouch!)kets ...
For the record, it was a prediction, not a command.

And, apparently, your prediction was correct.

I'm sorry to have caused such distress. My first version had no braces
at all and was all on one line. I broke it in three to try to be nice;
reasoning that whereas do takes a single statement or block and if IS
a single statement, therefore the flow should be sufficiently clear.

Isn't it in the grammar that a block (except for a function def) is a
special case of a statement which happens not to take terminating
semicolon? I'm too lazy to look it up, but that's the shape it took in
my memory. And this meme has yet to lead me astray.
 
G

Guest

Kuhl said:
Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way. I
believe there must be a better and simple way to do this check. How to
do it? BTW, I only want to treat the regular notation as a number. If
the argument is scientific notation, then I don't want to treat it as
a number. Thanks.

Something self-made for this purpose is the best way, IMHO.

typedef enum { false, true } BOOL;

BOOL isnum (char *s) {
int i;
BOOL num=true;

for (; *s && num; s++) {
if ((*s < '0' || *s > '9') && *s != '.')
num=false;
}

return num;
}
 
F

Flash Gordon

Kuhl said:
Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way. I
believe there must be a better and simple way to do this check. How to
do it? BTW, I only want to treat the regular notation as a number. If
the argument is scientific notation, then I don't want to treat it as
a number. Thanks.

Something self-made for this purpose is the best way, IMHO.

Only if you write it very carefully.
typedef enum { false, true } BOOL;

BOOL isnum (char *s) {
int i;
BOOL num=true;

for (; *s && num; s++) {
if ((*s < '0' || *s > '9') && *s != '.')
num=false;
}

return num;
}

Now try it with the string "..."
 
E

Eric Sosman

Kuhl said:
Hi, I am programming with C in Linux. I need to check whether an
argument in the command line is a number. For example, let's say check
whether argv[3] is a number or not. I can check it by checking and
analysing each character one by one. But this is not a good way. I
believe there must be a better and simple way to do this check. How to
do it? BTW, I only want to treat the regular notation as a number. If
the argument is scientific notation, then I don't want to treat it as
a number. Thanks.

Something self-made for this purpose is the best way, IMHO.

typedef enum { false, true } BOOL;

BOOL isnum (char *s) {
int i;
BOOL num=true;

for (; *s && num; s++) {
if ((*s < '0' || *s > '9') && *s != '.')
num=false;
}

return num;
}

This is a clear violation of the Seventh Commandment:

"Thou shalt study thy libraries and strive not to
reinvent them without cause, that thy code may be
short and readable and thy days pleasant and
productive."
<http://www.lysator.liu.se/c/ten-commandments.html>

In the case at hand, ponder:

#include <string.h>
int isnum(char *s) {
return s[ strspn(s,"0123456789.") ] == '\0';
}

Three further points worth noting: First, as Flash Gordon
has illustrated, both functions accept some non-numeric
inputs. Second, both versions *reject* some numeric inputs
like "-42". And finally, you have selected a reserved name
for the function, leading to undefined behavior.
 
L

luserXtrog

luserXtrog said:
[...]
Isn't it in the grammar that a block (except for a function def) is a
special case of a statement which happens not to take terminating
semicolon? I'm too lazy to look it up, but that's the shape it took in
my memory. And this meme has yet to lead me astray.

     A "block" is not a statement; it is a collection of statements
and declarations (6.8p3).  Some kinds of statements contain blocks
as part or all of their makeup: The compound statement in its entirety
is a block (6.8.2), the if and switch statements are blocks and can
contain subordinate blocks (6.8.4p3).

How did you find those sections without reading any of the surrounding
material? Everything is a statement.
Section 6.8.2, entitled "Compound statement", describes how a block
may be used wherever a statement is required.

Therefore, grammatically, according to the standard,

if (whatever) { do_something(); }

is a special case of

if (whatever) do_something();

..
I think I probably got this from Van Der Linden (which I lent to my
sister who lent it to my cousin. arg!). If memory serves, I liberated
the book from a locked cabinet labeled "Library"; so I suppose I can't
be too miffed. But I cannot recommend this book highly enough (though
I can't quite remember the title; it's got that rediscovered South
African prehistoric fish on the cover).
     After sticking my foot in my mouth yesterday and then applying
it to other parts of my anatomy, I spent a while looking at the
grammar.  One oddity I spotted might be useful to IOCCC entrants:

        #include <stdio.h>
        int main(void) {
            char *p = "Hello, world!\n";
            switch (*p) while (*p) putchar(*p++);
            return 0;
        }

Care to predict the output?

My guess is none at all (unless the "return 0;" is considered
output!).
 
J

jameskuyper

Eric Sosman wrote:
....
A "block" is not a statement; it is a collection of statements
and declarations (6.8p3). Some kinds of statements contain blocks
as part or all of their makeup: The compound statement in its entirety
is a block (6.8.2), the if and switch statements are blocks and can
contain subordinate blocks (6.8.4p3).

I would use exactly the same examples you gave as proof of the fact
that a block IS a statement, since a compound-statement, a selection-
statement, and a sub-statement are all examples of statements.
 
W

Willem

Eric Sosman wrote:
) #include <stdio.h>
) int main(void) {
) char *p = "Hello, world!\n";
) switch (*p) while (*p) putchar(*p++);
) return 0;
) }
)
) Care to predict the output?

How about this one:

#include <stdio.h>
int main(void) {
char *p = "Hello, world!\n";
switch (*p) while (*++p) default: putchar(*p);
return 0;
}


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
L

luserXtrog

luserXtrog said:
luserXtrog wrote:
[...]
Isn't it in the grammar that a block (except for a function def) is a
special case of a statement which happens not to take terminating
semicolon? I'm too lazy to look it up, but that's the shape it took in
my memory. And this meme has yet to lead me astray.
     A "block" is not a statement; it is a collection of statements
and declarations (6.8p3).  Some kinds of statements contain blocks
as part or all of their makeup: The compound statement in its entirety
is a block (6.8.2), the if and switch statements are blocks and can
contain subordinate blocks (6.8.4p3).
How did you find those sections without reading any of the surrounding
material? Everything is a statement.

     Nonsense.  `int i = 42;', for example, is not a statement.
`int main(void) { return 0; }' is not a statement.

My bad. I assumed the "Everything is a ..." form would be sufficient
indication of an overgeneralization. It was intended somehow to be
obviously incorrect but suggestive of the broader pattern.
All the good stuff is a statement.

cf 6.9.1
A function is defined with a compound statement (which is a block).

And then there's:
6.8 Statements and blocks
Syntax
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement

     6.8.2p1 gives the syntax of a compound statement, and 6.8.p2 says
in its entirety "A compound statement is a block," and that's all there
is in 6.8.2.  Where is the description you, er, describe?

     "A compound statement is a block" does not imply that all blocks are
compound statements.  For example, `if (a) b=42; else c=24;' has three
blocks, none of them compound statements (6.8.4p3).

But they're not blocks, either. They fail to be compound statements
because they are simple statements. Elementary statements.
     Right you are.  The "oddity" is the observation that a switch
statement does not in and of itself require a compound statement.

This oddity is to be observed with the constructs: if, if/else, while,
do/while, for, etc.
You can even put case and default labels in a bracketless switch:

        switch (*p) default: while (*p) case 'H': putchar(*p++);

... would output the famous greeting.

Now that's pretty snazzy!
 
K

Keith Thompson

Eric Sosman said:
luserXtrog said:
luserXtrog wrote:
[...]
Isn't it in the grammar that a block (except for a function def) is a
special case of a statement which happens not to take terminating
semicolon? I'm too lazy to look it up, but that's the shape it took in
my memory. And this meme has yet to lead me astray.
A "block" is not a statement; it is a collection of statements
and declarations (6.8p3). Some kinds of statements contain blocks
as part or all of their makeup: The compound statement in its entirety
is a block (6.8.2), the if and switch statements are blocks and can
contain subordinate blocks (6.8.4p3).

How did you find those sections without reading any of the surrounding
material? Everything is a statement.

Nonsense. `int i = 42;', for example, is not a statement.
`int main(void) { return 0; }' is not a statement.
Section 6.8.2, entitled "Compound statement", describes how a block
may be used wherever a statement is required.

6.8.2p1 gives the syntax of a compound statement, and 6.8.p2 says
in its entirety "A compound statement is a block," and that's all there
is in 6.8.2. Where is the description you, er, describe?

"A compound statement is a block" does not imply that all blocks are
compound statements. For example, `if (a) b=42; else c=24;' has three
blocks, none of them compound statements (6.8.4p3).

You're right. I've always assumed that "block" and "compound
statement" are synonymous, but they're not. But I dislike the way the
standard expresses this.

C99 6.8p2 purports to define the term "block":

A _block_ allows a set of declarations and statements to be
grouped into one syntactic unit. The initializers of objects that
have automatic storage duration, and the variable length array
declarators of ordinary identifiers with block scope, are
evaluated and the values are stored in the objects (including
storing an indeterminate value in objects without an initializer)
each time the declaration is reached in the order of execution, as
if it were a statement, and within each declaration in the order
that declarators appear.

But this definition doesn't really define what is and is not a block.
I should be able to read a definition for a term and be able to
determine unambiguously whether a given thing is an example of that
term or not, perhaps reading other text to understand the meanings of
terms used in the definition. The above is a statement about blocks;
it's not a definition of the term.

6.8.2p2 says:

A _compound statement_ is a block.

6.8.4p3 says:

A selection statement is a block whose scope is a strict subset of
the scope of its enclosing block. Each associated substatement is
also a block whose scope is a strict subset of the scope of the
selection statement.

6.8.5p5 says:

An iteration statement is a block whose scope is a strict subset
of the scope of its enclosing block. The loop body is also a block
whose scope is a strict subset of the scope of the iteration
statement.

So a statement is a block if it's a compound statement, a selection
statement or a substatement thereof, or an iteration statement or a
substatement thereof. In the following:

if (condition)
return 1;
return 0;

"return 1;" is a block but "return 0;" isn't.

What's the point? Certain declarations have block scope, but you
can only have a declaration within a compound statement anyway; this:

if (x == 3)
int y;

is illegal. (That's not quite true; a for statement can have a
declaration.) If the language definition were changed so that only a
compound statement is a block, what, if anything, would break?
 
K

Keith Thompson

luserXtrog said:
But they're not blocks, either. They fail to be compound statements
because they are simple statements. Elementary statements.

Yes, they are blocks; see my other response. (I learned that while
checking the standard in an attempt to prove that they're not.)
 
L

luserXtrog

Eric Sosman said:
luserXtrog said:
luserXtrog wrote:
[...]
Isn't it in the grammar that a block (except for a function def) is a
special case of a statement which happens not to take terminating
semicolon? I'm too lazy to look it up, but that's the shape it took in
my memory. And this meme has yet to lead me astray.
     A "block" is not a statement; it is a collection of statements
and declarations (6.8p3).  Some kinds of statements contain blocks
as part or all of their makeup: The compound statement in its entirety
is a block (6.8.2), the if and switch statements are blocks and can
contain subordinate blocks (6.8.4p3).
How did you find those sections without reading any of the surrounding
material? Everything is a statement.
    Nonsense.  `int i = 42;', for example, is not a statement.
`int main(void) { return 0; }' is not a statement.

I explicitly mentioned function definitions as another case entirely.
You have not been paying attention.
You're right.  I've always assumed that "block" and "compound
statement" are synonymous, but they're not.  But I dislike the way the
standard expresses this.

C99 6.8p2 purports to define the term "block":

    A _block_ allows a set of declarations and statements to be
    grouped into one syntactic unit.  The initializers of objects that
    have automatic storage duration, and the variable length array
    declarators of ordinary identifiers with block scope, are
    evaluated and the values are stored in the objects (including
    storing an indeterminate value in objects without an initializer)
    each time the declaration is reached in the order of execution, as
    if it were a statement, and within each declaration in the order
    that declarators appear.

But this definition doesn't really define what is and is not a block.
I should be able to read a definition for a term and be able to
determine unambiguously whether a given thing is an example of that
term or not, perhaps reading other text to understand the meanings of
terms used in the definition.  The above is a statement about blocks;
it's not a definition of the term.

6.8.2p2 says:

    A _compound statement_ is a block.

6.8.4p3 says:

    A selection statement is a block whose scope is a strict subset of
    the scope of its enclosing block. Each associated substatement is
    also a block whose scope is a strict subset of the scope of the
    selection statement.

6.8.5p5 says:

    An iteration statement is a block whose scope is a strict subset
    of the scope of its enclosing block. The loop body is also a block
    whose scope is a strict subset of the scope of the iteration
    statement.

So a statement is a block if it's a compound statement, a selection
statement or a substatement thereof, or an iteration statement or a
substatement thereof.  In the following:

    if (condition)
        return 1;
    return 0;

"return 1;" is a block but "return 0;" isn't.

What's the point?  Certain declarations have block scope, but you
can only have a declaration within a compound statement anyway; this:

    if (x == 3)
        int y;

is illegal.  (That's not quite true; a for statement can have a
declaration.)  

Which is just some bullshit adopted from C++. not C90. not portable.
This is the oddditty. Not the other way 'round.

If the language definition were changed so that only a
compound statement is a block, what, if anything, would break?

I don't ever understand that question.
It seems like you guys are operating with some conceptual model that
shoots straight to some virtual machine assembler listing, where the
blocks have nice rectangular borders around them. I think you need to
dwell in the abstract syntax tree a little more.

You seem to be mining the footnotes. I think you need to look at the
pictures more. In the grammar it's all about statements. Statement
this; statement that; conditional statement; iterative statement.

The word 'block' is your block.
 
H

Harald van Dijk

If the language definition were changed so that only a compound
statement is a block, what, if anything, would break?

After

for (int i = 0; i <= 10; i++) { ... }

the i should go out of scope, if only so that

for (int i = 0; i <= 10; i++) { ... }
for (int i = 0; i <= 10; i++) { ... }

does not give an error for a redefinition of i.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top