Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C scanf behaving unexpectedly with %i to scan dates [duplicate]

Tags:

c

scanf

For some reason, when I run my program it is not giving me the option to type numbers for the statements associated with day1 and year2. Why is it doing this?

#include <stdio.h>

int main(void ) {

    int day1, day2, month1, month2, year1, year2;

    printf("Enter date 1 mm\n");
    scanf("%i", &month1);

    printf("Enter date 1 dd\n");
    scanf("%i", &day1);

    printf("Enter date 1 yyyy\n");
    scanf("%i", &year1);

    printf("Enter date 2 mm\n");
    scanf("%i", &month2);

    printf("Enter date 2 dd\n");
    scanf("%i", &day2);

    printf("Enter date 2 yyyy\n");
    scanf("%i", &year2);

    return 0;
}
like image 989
Frank Tocci Avatar asked Apr 04 '15 02:04

Frank Tocci


1 Answers

Are you typing 08 or 09 for the first mm value?

If so, that's the trouble: the %i conversion specification accepts 0x before a hex value, and 0 before an octal value (see the POSIX specification for scanf()). If you type 08 or 09, only the zero is valid as octal, so it leaves the 8 or 9 in the input, which is immediately read as the day1 value. Similarly, you probably enter 08 or 09 for day2, and the same failure occurs so day2 contains 0 and year2 contains 8 or 9.

You could help yourself, and everyone else, by:

  1. Checking that the scanf() calls are successful.
  2. Printing the values that are entered from within the program.
  3. Including a transcript of the program running.

For example:

#include <stdio.h>

int main(void ) {

    int day1, day2, month1, month2, year1, year2;

    printf("Enter date 1 mm\n");
    scanf("%i", &month1);

    printf("Enter date 1 dd\n");
    scanf("%i", &day1);

    printf("Enter date 1 yyyy\n");
    scanf("%i", &year1);

    printf("Enter date 2 mm\n");
    scanf("%i", &month2);

    printf("Enter date 2 dd\n");
    scanf("%i", &day2);

    printf("Enter date 2 yyyy\n");
    scanf("%i", &year2);

    printf("%.4d-%.2d-%.2d to %.4d-%.2d-%.2d\n",
           year1, month1, day1, year2, month2, day2);

    return 0;
}

Sample run:

$ ./date1
Enter date 1 mm
08
Enter date 1 dd
Enter date 1 yyyy
1999
Enter date 2 mm
12
Enter date 2 dd
09
Enter date 2 yyyy
1999-00-08 to 0009-12-00
$

The code doesn't check the scanf() calls, but it does illustrate the behaviour you saw.

Fix

If you want the numbers to be decimal even with leading zeroes, use %d instead of %i.

Only the hardiest C programmers enter dates in octal or hex.

like image 104
Jonathan Leffler Avatar answered Oct 10 '22 13:10

Jonathan Leffler