Jcht
Jcht

Reputation: 3

Validate input of scanf

I need to read hours:minutes in this exact format. I use:

    int hours, minutes;

    if (scanf("%d:%d", &hours, &minutes)!= 2)
    {
        printf("Wrong input.\n");
        return 1;
    }
else if (minutes>60 || minutes<0 || hours<0)
    {
        printf("Wrong input.\n");
        return 1;
    }

    time = hours*60 + minutes;

    /*read another time interval */
     if (scanf("%d:%d", &hours, &minutes)!= 2)
    {
        printf("Wrong input 2.\n");
        return 1;
    }
else if (minutes>60 || minutes<0 || hours<0)
    {
        printf("Wrong input 2.\n");
        return 1;
    }
   ...

works fine, but I need to get "wrong input" also in situations that someone enters e.g. 5:38abc

Upvotes: 0

Views: 176

Answers (2)

The traditional way is to read an entire line using getline(3) or fgets(3) (so the line is in a buffer), then to parse that line. You could use sscanf(3) - perhaps with its %n specifier - or you could parse that line more manually with e.g. strtol(3) (which sets the end pointer).

So something like:

int endpos= -1;
char linbuf[32];
memset(linbuf, 0, sizeof(linbuf));
if (!fgets(linbuf, sizeof(linbuf)) exit(EXIT_FAILURE);
if (sscanf(linbuf, "%O2d:%02d%n", &hour, &minute, &endpos)<2)
   exit(EXIT_FAILURE);
if (endpos!=6) exit(EXIT_FAILURE);
if (hour<0 || minute<0 || hour>=24 || minute>=60) exit(EXIT_FAILURE); 

Of course you would replace the exit(EXIT_FAILURE); with a more user-friendly rejection.

BTW, you should specify if 1:2 is acceptable input or if you require 01:02. And would you accept an empty line as representing noon?

Upvotes: 0

Barmar
Barmar

Reputation: 780818

Add an operator to the format string to match the newline:

int hours, minutes;
char str[2];

if (scanf("%d:%d%1[\n]", &hours, &minutes, str)!= 3)

%[\n] matches newline characters, and the field width 1 makes it stop matching after exactly 1 character.

Upvotes: 1

Related Questions