C
Count Dracula
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;
}
--
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;
}
--