Checking for valid number syntax

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Count Dracula

    Checking for valid number syntax

    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(co nst 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(cons t 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(buff er1) && validinteger(bu ffer2);
    }

    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;
    }

    --

  • Michal Nazarewicz

    #2
    Re: Checking for valid number syntax

    "Count Dracula" <Levent.Kitis@n avy.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(con st 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*chr ome.pl>--ooO--(_)--Ooo--

    Comment

    • Fred Kleinschmidt

      #3
      Re: Checking for valid number syntax


      "Michal Nazarewicz" <mina86@tlen.pl wrote in message
      news:87lkl2b9e3 .fsf@erwin.mina 86.com...
      "Count Dracula" <Levent.Kitis@n avy.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(con st 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
      ..


      Comment

      • Michal Nazarewicz

        #4
        Re: Checking for valid number syntax

        >"Count Dracula" <Levent.Kitis@n avy.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" <mina86@tlen.pl wrote in message
        news:87lkl2b9e3 .fsf@erwin.mina 86.com...
        >You can always do the following:
        [code removed]

        "Fred Kleinschmidt" <fred.l.kleinms chmidt@boeing.c omwrites:
        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*chr ome.pl>--ooO--(_)--Ooo--

        Comment

        • Jorgen Grahn

          #5
          Re: Checking for valid number syntax

          On Thu, 21 Dec 2006 11:42:58 +0100, Michal Nazarewicz <mina86@tlen.pl wrote:
          >>"Count Dracula" <Levent.Kitis@n avy.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" <mina86@tlen.pl wrote in message
          >news:87lkl2b9e 3.fsf@erwin.min a86.com...
          >>You can always do the following:
          [code removed]
          >
          "Fred Kleinschmidt" <fred.l.kleinms chmidt@boeing.c omwrites:
          >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.progra mmering.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.dyn dns.org R'lyeh wgah'nagl fhtagn!

          Comment

          • Random832

            #6
            Re: Checking for valid number syntax

            2006-12-21 <slrneol9jd.tcj .grahn+nntp@fra ilea.sa.invalid >,
            Jorgen Grahn wrote:
            On Thu, 21 Dec 2006 11:42:58 +0100, Michal Nazarewicz <mina86@tlen.pl wrote:
            >>>"Count Dracula" <Levent.Kitis@n avy.milwrites:
            >>>>The following three functions check whether a given string
            >>>>represent s a valid number. They require that the entire string
            >>>>represent
            >>>>a number, unlike strtod which accepts strings like
            >>>>"99rQF" and returns 99.
            >>
            >>"Michal Nazarewicz" <mina86@tlen.pl wrote in message
            >>news:87lkl2b9 e3.fsf@erwin.mi na86.com...
            >>>You can always do the following:
            >[code removed]
            >>
            >"Fred Kleinschmidt" <fred.l.kleinms chmidt@boeing.c omwrites:
            >>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"?

            Comment

            • Ben Pfaff

              #7
              Re: Checking for valid number syntax

              Jorgen Grahn <grahn+nntp@sni pabacken.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[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
              \n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
              );while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
              );}return 0;}

              Comment

              • Jalapeno

                #8
                Re: Checking for valid number syntax


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

                KvTUbCPQVKIVeif NHJRMZhj

                as output on my system (ebcdic).

                Comment

                • Ben Pfaff

                  #9
                  Re: Checking for valid number syntax

                  "Jalapeno" <jalapeno1@mac. comwrites:
                  Ben Pfaff wrote:
                  (in his sig)
                  >int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
                  > \n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
                  >);while(*q){i+ =strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
                  >);}return 0;}
                  >
                  Is that an ascii thing?
                  No.
                  I get
                  >
                  KvTUbCPQVKIVeif NHJRMZhj
                  >
                  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.
                  --
                  "...deficie nt support can be a virtue.
                  It keeps the amateurs off."
                  --Bjarne Stroustrup

                  Comment

                  Working...