1

I am making an app that records the time, userID, and weight. How can I check if the first token passed is an integer? I thought I would use isdigit, but that just works for single chars. I want to output Invalid time if the first token is not an integer. I'm currently using

sscanf(userInput, "%d %s %f", &timestamp, userID, &weight);

If the first token is not an integer (has alphabets for example) I still get a number for the variable timestamp,, which I don't want.

int main()
{
   char userInput[99];
   int timestamp, timestampT = 0;
   char userID[31];
   userID[0] = 0;
   float weight, weightT, day, rateW;

   while(fgets(userInput, 99, stdin) != NULL){
       sscanf(userInput, "%d %s %f", &timestamp, userID, &weight);

       if(timestamp == 0 ){
           printf("%s\n", "Invalid time");
       }
       else if(!isalpha(userID[0]) || userID[0]=='_' || userID[0] == 0){
           printf("%s\n", "Illegal userID");
       }
       else if(weight < 30.0 || weight > 300.0){
           printf("%s\n", "Illegal weight");
       }
       else if(timestampT > 0){
           day = timestampT/86400;
           rateW = (weightT -weight)/(day - timestamp/86400);
           if(rateW > 10.0 || rateW < -10.0){
               printf("%s\n", "Suspiciously large weight change");
           }

       }
       else{
           printf("%d %s %f \n", timestamp, userID, weight);
           timestampT = timestamp;
           timestamp = 0;
           weightT = weight;
       }

       userID[0] = 0;
   }
}
3
  • 1
    build another string using the results of the sscanf, then compare the original to the rebuild string. if they're different, then something didn't convert correctly. e.g. foo = printf('%d %s, %f', the, values, here); if (!strcmp(foo, userinput)) { ruh_roh(); } Commented Jan 21, 2014 at 18:22
  • 1
    Start by using the result of sscanf() to determine how many parameters were successfully parsed. Heed the Sixth Commandment Commented Jan 21, 2014 at 18:27
  • You can check all characters of a string with isdigit for your timestamp or with isalpha for your ID. (Better write functions for that.) Or you could read the time in as string in your first sscanf and then run sscanf(..., "%d", ...)` on that string. Commented Jan 21, 2014 at 18:29

1 Answer 1

3

Easy way:

char dummy;
sscanf( userInput, "%d%c %s %f", &timestamp, &dummy, userId, &weight );
if ( !isspace( dummy ))
   // invalid timestamp input, handle as appropriate

The %d conversion specifier tells sscanf to leave the first non-digit character in the input stream, which will be picked up by the %c conversion specifier. If this character is anything other than whitespace, then the input was not a valid integer string.

Less easy, but IMO the more robust way:

First, read your timestamp as text:

char timestampStr[N+1]; // where N is the number of digits in the time stamp
...
sscanf(userInput, "%s %s %f", timestampStr, userID, &weight);

Then use the strtol library function to convert the text to an integer value:

char *chk;
int tmp = (int) strtol( timestampStr, &chk, 10 );

After the conversion, chk will point to the first non-digit character in timestampStr; if this character is anything other than whitespace or the 0 terminator, then the input string was not a valid integer:

if ( *chk == 0 || isspace( *chk ))
{
  timestamp = tmp;
}
else
{
  // invalid timestamp input, handle as appropriate
}

I prefer this method because it won't assign anything to timestamp if the input is invalid; this may or may not matter for your purposes.

EDIT

As chux points out, you should also check the return value of sscanf (I rarely use the *scanf functions for interactive input, so I never think about that). In the first case, if the result is < 4, then you have a problem regardless of the timestamp and should throw the whole line away. Similarly, in the second case, if the result is < 3, you didn't get the input you wanted and you should throw the whole line away.

In practice, what I do is use fgets to read the line and then break it into tokens using strtok, and then use strtol or strtod to do any numeric conversions as necessary.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.