By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,445 Members | 1,329 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,445 IT Pros & Developers. It's quick & easy.

Checking for valid number syntax

P: n/a
The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99. Is there a way to make strtod and friends
behave like the functions below? Is there some room for improvement
of the functions below from the point of view of speed of execution?
The code below should be compilable.

Thanks,

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int validinteger(const char* s)
{
/* input string s may have leading or trailing blanks */
const int false = 0;
size_t n = 0, N = strlen(s);
int state = 0;
int c;
while (n < N)
{
c = s[n];
switch (state)
{
case 0:
if (isdigit(c))
state = 1;
else if (c == '-' || c == '+')
state = 2;
else if (!isspace(c))
return false;
break;
case 1:
if (isspace(c))
state = 3;
else if (!isdigit(c))
return false;
break;
case 2:
if (isdigit(c))
state = 4;
else
return false;
break;
case 3:
if (!isspace(c))
return false;
break;
case 4:
if (isspace(c))
state = 3;
else if (!isdigit(c))
return false;
break;
}
++n;
}
return state == 1 || state == 3 || state == 4;
}

int validfloat(const char* s)
{
/* input string s may have leading or trailing blanks */
const int false = 0;
size_t n = 0, N = strlen(s);
int state = 0;
int c;
while (n < N)
{
c = s[n];
switch (state)
{
case 0:
if (isdigit(c))
state = 1;
else if (c == '-' || c == '+')
state = 2;
else if (c == '.')
state = 5;
else if (!isspace(c))
return false;
break;
case 1:
if (isspace(c))
state = 6;
else if (c == '.')
state = 3;
else if (!isdigit(c))
return false;
break;
case 2:
if (isdigit(c))
state = 1;
else if (c == '.')
state = 5;
else
return false;
break;
case 3:
if (isdigit(c))
state = 4;
else if (isspace(c))
state = 6;
else
return false;
break;
case 4:
if (isspace(c))
state = 6;
else if (!isdigit(c))
return false;
break;
case 5:
if (isdigit(c))
state = 4;
else
return false;
break;
case 6:
if (!isspace(c))
return false;
break;
}
++n;
}
return state == 1 || state == 3 || state == 4 || state == 6;
}

int validreal(const char* s)
{
/* input string may have leading or trailing blanks */
int k, c;
char buffer1[64], buffer2[64];
const char *n;
char* p = strchr(s, 'e');
char* q = NULL;
if (p == NULL)
q = strchr(s, 'E');

if (p == NULL && q == NULL)
return validfloat(s);
if (p != NULL)
c = *p;
else if (q != NULL)
c = *q;

n = &s[0];
k = 0;
while (*n != c)
{
buffer1[k] = *n;
++k;
++n;
}
buffer1[k] = '\0';
++n;
k = 0;
while (*n != '\0')
{
buffer2[k] = *n;
++k;
++n;
}
buffer2[k] = '\0';
return validfloat(buffer1) && validinteger(buffer2);
}

int main (int argc, char** argv)
{
int n;
int x;
for (n = 1; n < argc; ++n)
{
x = validreal(argv[n]);
printf("%12s %10d \n", argv[n], x);
}
return 0;
}

--

Dec 20 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
"Count Dracula" <Le**********@navy.milwrites:
The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99.
You can always do the following:

#v+
#include <stdlib.h>
/* ... *

int validint(const char *str, long *val) {
if (!str || !*str) {
return 0;
} else {
char *end;
long v = strtol(str, &end, 0);
if (*end) {
return 0;
} else {
*val = v;
return 1;
}
}
}

int validdouble(const char *str, double *val) {
if (!str || !*str) {
return 0;
} else {
char *end;
double v = strtod(str, &end);
if (*end) {
return 0;
} else {
*val = v;
return 1;
}
}
}
--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>---<jid:mina86*chrome.pl>--ooO--(_)--Ooo--
Dec 20 '06 #2

P: n/a

"Michal Nazarewicz" <mi****@tlen.plwrote in message
news:87************@erwin.mina86.com...
"Count Dracula" <Le**********@navy.milwrites:
>The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99.

You can always do the following:

#v+
#include <stdlib.h>
/* ... *

int validint(const char *str, long *val) {
if (!str || !*str) {
return 0;
} else {
char *end;
long v = strtol(str, &end, 0);
if (*end) {
return 0;
} else {
*val = v;
return 1;
}
}
}

int validdouble(const char *str, double *val) {
if (!str || !*str) {
return 0;
} else {
char *end;
double v = strtod(str, &end);
if (*end) {
return 0;
} else {
*val = v;
return 1;
}
}
}

Why not return:
-1 on success,
0 for null or empty string
end-str for bad format

This gives the index of the offending character.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
..
Dec 20 '06 #3

P: n/a
>"Count Dracula" <Le**********@navy.milwrites:
>>The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99.
"Michal Nazarewicz" <mi****@tlen.plwrote in message
news:87************@erwin.mina86.com...
>You can always do the following:
[code removed]

"Fred Kleinschmidt" <fr******************@boeing.comwrites:
Why not return:
-1 on success,
0 for null or empty string
end-str for bad format

This gives the index of the offending character.
But of course - if you'd like to. :) My point is that there's no need
to write those functions from stretch but strtol() and strtod() can be
used.

#v+
#include <stdlib.h>

long parseint(const char *str, long *val) {
if (!str || !*str) {
return 0;
} else {
char *end;
long v = strtol(str, &end, 0);
if (*end) return end - str;
if (val) *val = v;
return -1;
}
}
#v-
--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>---<jid:mina86*chrome.pl>--ooO--(_)--Ooo--
Dec 21 '06 #4

P: n/a
On Thu, 21 Dec 2006 11:42:58 +0100, Michal Nazarewicz <mi****@tlen.plwrote:
>>"Count Dracula" <Le**********@navy.milwrites:
The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99.
>"Michal Nazarewicz" <mi****@tlen.plwrote in message
news:87************@erwin.mina86.com...
>>You can always do the following:
[code removed]

"Fred Kleinschmidt" <fr******************@boeing.comwrites:
>Why not return:
-1 on success,
0 for null or empty string
end-str for bad format

This gives the index of the offending character.

But of course - if you'd like to. :) My point is that there's no need
to write those functions from stretch but strtol() and strtod() can be
used.
Also worth to keep in mind: both strtol() and strtod() accept a much wider
syntax than the original poster's code (hexadecimal, "NaN", etc etc). And he
accepted one thing those functions don't: leading/trailing whitespace.

We had a long discussion about this recently in
se.dator.programmering.diverse, but of course that's in Swedish ...

But yes, he's probably better off with the standard functions.

/Jorgen

--
// Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
\X/ snipabacken.dyndns.org R'lyeh wgah'nagl fhtagn!
Dec 21 '06 #5

P: n/a
2006-12-21 <sl***********************@frailea.sa.invalid>,
Jorgen Grahn wrote:
On Thu, 21 Dec 2006 11:42:58 +0100, Michal Nazarewicz <mi****@tlen.plwrote:
>>>"Count Dracula" <Le**********@navy.milwrites:
The following three functions check whether a given string
represents a valid number. They require that the entire string
represent
a number, unlike strtod which accepts strings like
"99rQF" and returns 99.
>>"Michal Nazarewicz" <mi****@tlen.plwrote in message
news:87************@erwin.mina86.com...
You can always do the following:
[code removed]

"Fred Kleinschmidt" <fr******************@boeing.comwrites:
>>Why not return:
-1 on success,
0 for null or empty string
end-str for bad format

This gives the index of the offending character.

But of course - if you'd like to. :) My point is that there's no need
to write those functions from stretch but strtol() and strtod() can be
used.

Also worth to keep in mind: both strtol() and strtod() accept a much wider
syntax than the original poster's code (hexadecimal, "NaN", etc etc). And he
accepted one thing those functions don't: leading/trailing whitespace.
In what way do those functions reject trailing whitespace in the sense
that they can be said to accept trailing "rQF"?
Dec 21 '06 #6

P: n/a
Jorgen Grahn <gr********@snipabacken.dyndns.orgwrites:
Also worth to keep in mind: both strtol() and strtod() accept a much wider
syntax than the original poster's code (hexadecimal, "NaN", etc etc). And he
accepted one thing those functions don't: leading/trailing whitespace.
strtol and strtod can both successfully convert strings that
contain leading and trailing white-space characters.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Dec 21 '06 #7

P: n/a

Ben Pfaff wrote:
(in his sig)
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Is that an ascii thing? I get

KvTUbCPQVKIVeifNHJRMZhj

as output on my system (ebcdic).

Dec 21 '06 #8

P: n/a
"Jalapeno" <ja*******@mac.comwrites:
Ben Pfaff wrote:
(in his sig)
>int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}

Is that an ascii thing?
No.
I get

KvTUbCPQVKIVeifNHJRMZhj

as output on my system (ebcdic).
Perhaps you cut and pasted it incorrectly, e.g. by omitting the
space at the beginning of the second line.
--
"...deficient support can be a virtue.
It keeps the amateurs off."
--Bjarne Stroustrup
Dec 21 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.