Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make scanf() scan in integers one digit at a time?

Tags:

c

scanf

I want to scan in a date in the form of mm/dd, so I've written this code:

#include <stdio.h>

int main (void)
{
  int start_date[4];

  scanf("%d%d/%d%d", &start_date[0], &start_date[1], &start_date[2], &start_date[3]);

  printf("%d%d%d%d\n", start_date[0], start_date[1], start_date[2], start_date[3]);

  return 0;
}

But when I enter the following for example:

04/20

scanf() reads this

4-419644000

How do I make it so that when I print out each element in start_date, I get this:

0420

when I enter the input from earlier?


2 Answers

Reading one digit at a time

Use %1d:

int n = scanf("%1d%1d/%1d%1d", &start_date[0], &start_date[1], &start_date[2], &start_date[3]);
if (n != 4) { …handle error… }

Note that this will accept both:

19/96

and

1 9/
9

6

as valid inputs. If you need the digits to be contiguous, you have to work harder. In general, it is usually best to read a line with fgets() (or POSIX's getline()) and then parse the line with sscanf(). You can also consider checking the length of the string, etc.

What went wrong?

Incidentally, you said:

But when I enter the following for example:

04/20

scanf() reads this

4-419644000

What happens here is that the 04 is read by the first %d; the second %d fails because / doesn't match a number, so nothing is written to &start_date[1] (or the other two items), and scanf() returns 1. Since you didn't check the return value, you weren't aware of the problem. Note that the check should be as I showed (n != 4 where 4 is the number of items you expect to be converted). Checking for EOF would not work correctly; there wasn't an EOF on the file, but there was a conversion failure. Since you printed an uninitialized variable, the value you got was indeterminate ('undefined behaviour' in the jargon); a largish negative number is reasonable (as is any other value whatsoever, or a crash, or …). In fact, you have three indeterminate numbers smushed together, of which only the first is negative. Avoid undefined behaviour; always check that your input operations succeed — and don't use the results if they fail. (Or, at least, be very cautious about using the results if they fail; you need to be sure you know what's going on.)

like image 67
Jonathan Leffler Avatar answered Feb 02 '26 11:02

Jonathan Leffler


The %d would consume the string "04", if you want to input digit by digit really, try %c, then adjust them to digit:

char start_data[4];
scanf("%c%c/%c%c", &start_date[0], &start_date[1], &start_date[2], &start_date[3]);
start_data[0] -= '0';
start_data[1] -= '0';
start_data[2] -= '0';
start_data[3] -= '0';

Another way, you can just input mm and dd and do arithmetic on it:

int mm, dd;
scanf("%d/%d", &mm, &dd);
int m0 = mm % 10;
int m1 = mm / 10;
int d0 = dd % 10;
int d1 = dd / 10;
like image 36
fluter Avatar answered Feb 02 '26 10:02

fluter