Thread: Strtok() - int or float it be?

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    84

    Unhappy Strtok() - int or float it be?

    So, I am utilizing the string library...

    Code:
    str = strtok(line, ",");
    variable = atof(str);
    
    if (sizeof(variable) == sizeof(float)) {
       var_i_or_f = 1;
       variable = atof(str);
       }
    else if(sizeof(variable) == sizeof(int)) {
       var_i_or_f = 0;
       variable = atoi(str);
        }
    My question is: is their a way to know or test to see if str will be a int or a float?

    At first, I thought I could use sizeof() and conditional statements to test before realizing that I am using atof to get str. Thus can't check it if its one or the other since im using it... Trouble is that the data switches between int and float so their is no prescribed way to know which it will be beforehand.

    Is this possible.

    Sorry about my code: that is from memory - it compiles correctly but what I may have typed HERE may have an error in it.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I think you will have to do something like:

    if (strchr(str,'.')) {

    to decide.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Feb 2010
    Posts
    84

    Question

    Quote Originally Posted by MK27 View Post
    I think you will have to do something like:

    if (strchr(str,'.')) {

    to decide.
    Ok, strchr() returns a pointer to the first occurrence of character in the C string str. So, essentially, looks to see if str has a decimal point - thus if its a float value or an int. BUT, by using strchr do we lose what str originally was assigned/given? Does this string library function modify what str originally was, is what i mean...

    I mean if we did it that way:

    Code:
    str = strtok(line, ",");
    if (strchr(str,'.')) {
       variable = atof(str)
    else (variable = atoi(str))
    I feel that lost in this, is what str was originally assigned when it was given a value by strtok()....

    Thoughts?

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Nope. strchr takes a const char *, so it cannot change the passed string.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #5
    Registered User
    Join Date
    Feb 2010
    Posts
    84
    Neat - works groovy. So by its description of "pointer to the first occurrence of character in the C string str.", what it returns is the location of the "." and thus, preserving what str was assigned!

    correct?

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Yeah, if there's no "." it returns NULL. This is a "truth test":
    Code:
    if (strchr(str,'.'))
    means:
    Code:
    if (strchr(str,'.') != NULL)
    The opposite:
    Code:
    if (!strchr(str,'.')) 
    // means:
    if (strchr(str,'.') == NULL)
    Because you don't care where it is, just whether it is there. Or not.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by towed View Post
    My question is: is their a way to know or test to see if str will be a int or a float?
    Many ints will also be floats. I would choose to use strtol and strtof to attempt conversion of the text. If either is successful, you know what you got. If neither is successful, odds are it was neither. The order of calling these two allows you to have preference for one or the other. Something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    union uType
    {
       int   i;
       float f;
    };
    
    struct tType
    {
       enum eType
       {
          TYPE_INT, TYPE_FLOAT, TYPE_OTHER, TYPE_TOTAL
       } type;
       union uType value;
    };
    
    int foo(struct tType *data, const char *text)
    {
       char *end;
       data->value.i = strtol(text, &end, 10);
       if ( end > text && *end == '\0' )
       {
          data->type = TYPE_INT;
          return 1;
       }
       data->value.f = strtof(text, &end);
       if ( end > text && *end == '\0' )
       {
          data->type = TYPE_FLOAT;
          return 1;
       }
       data->type = TYPE_OTHER;
       return 0;
    }
    
    int main() 
    {
       const char *input[] =
       {
          "",
          "-123",
          "-123.45",
          "123E-2",
          "123abc",
          "xyz",
          "123E2",
          "1.23.E2",
       };
       size_t i;
       for ( i = 0; i < sizeof input / sizeof *input; ++i )
       {
          struct tType data;
          int result = foo(&data, input[i]);
          printf("\"%s\" : ", input[i]);
          switch ( data.type )
          {
          case TYPE_INT:   printf("TYPE_INT   %d", data.value.i); break;
          case TYPE_FLOAT: printf("TYPE_FLOAT %g", data.value.f); break;
          default:         fputs("TYPE_OTHER", stdout); break;
          }
          putchar('\n');
       }
       return 0;
    }
    
    /* my output
    "" : TYPE_OTHER
    "-123" : TYPE_INT   -123
    "-123.45" : TYPE_FLOAT -123.45
    "123E-2" : TYPE_FLOAT 1.23
    "123abc" : TYPE_OTHER
    "xyz" : TYPE_OTHER
    "123E2" : TYPE_FLOAT 12300
    "1.23.E2" : TYPE_OTHER
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Good one.

    I would just check for the dot and then sscanf one way or the other tho -- if that fails: NAN. Who cares about those fancy smancy scientific numbers or whatever they are called.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Feb 2010
    Posts
    84

    Unhappy

    Interesting - I am doing something akin to MK27. I do now ahead that it will be either float or int so I feel looking for the "." is efficient.

    Anywho... New stumbling block in regards to what I was doing.

    Code:
    str = strtok(line, ",");
    Is what I use, but I encountered a situation where there is an variable pass the last ","
    i.e.
    Line 1: 3.1, 2, 1
    Line 2: 3, 14.25, 131

    How can the last variable be read from Line 1 since it has no token to search?

    I immediately looked at strtok(line, " ") and strtok(line, "\n") but got an compiler error (NULL is returned).

    Secondly, tried strncpy, similar to strtok except precisely n characters are written into s1 and s1 is returned.
    i.e.
    strncpy(str, NULL, 1);

    But this results in a seg fault - even though no error messages are given.


    Any thoughts?

  10. #10
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Quote Originally Posted by towed View Post
    Code:
    str = strtok(line, ",");
    Is what I use, but I encountered a situation where there is an variable pass the last ","
    i.e.
    Line 1: 3.1, 2, 1
    Line 2: 3, 14.25, 131

    How can the last variable be read from Line 1 since it has no token to search?

    I immediately looked at strtok(line, " ") and strtok(line, "\n") but got an compiler error (NULL is returned).
    Code:
    strtok(line, " ,\n");
    will break on a space, a comma, or a newline, this might work depending on if your line retains the newline or not. fgets does retain the newline.

    Using strchr to differentiate a float from a int is hackish, IMO. Any parseable int is also a parsable float, so I'd use strtod (or equivalent) to parse floats.
    Last edited by MacNilly; 02-24-2010 at 11:23 AM. Reason: minor fix

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  2. memory leak
    By aruna1 in forum C++ Programming
    Replies: 3
    Last Post: 08-17-2008, 10:28 PM
  3. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  4. Replies: 2
    Last Post: 03-24-2006, 08:36 PM
  5. My graphics library
    By stupid_mutt in forum C Programming
    Replies: 3
    Last Post: 11-26-2001, 06:05 PM