5

Hi I am now learning the C language and I have a little problem with a exercise of the book I read. My code is this:

#include<stdio.h>
int main()
{
  unsigned char one=0;
  unsigned char two=0;
  printf("Quantity 1 = ");
  scanf("%d",&one);
  printf("Quantity 2 = ");
  scanf("%d",&two);
  printf("The value is %d",one);
  return 0;
}

Why when I am trying to see the value of one the initial value appears and not the value after the scanf?

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
paulakis
  • 89
  • 2
  • 7
  • Welcome to SO. Nice example demonstrating your question. – chux - Reinstate Monica Aug 21 '13 at 19:04
  • As given on the link by @Shade below, if you want to use `unsigned char` as variable type, you can use `%c` or `%hhu` format specifier – 0xF1 Aug 21 '13 at 19:07
  • The root cause here is the same issue addressed in [When using and int to read character, why is the value 4096 + ascii](http://stackoverflow.com/q/4973125/1281433). `scanf` can store values, but since an `unsigned char` is not the same size as an `int` (which `%d` expects), the `scanf` receives is stored in the place that `printf` expects it. Also see [scanf and keeping char as an integer](http://stackoverflow.com/q/17643453/1281433). – Joshua Taylor Aug 21 '13 at 19:24
  • @chux : A doubt: Is `%hhd` ok with `unsigned char`? – 0xF1 Aug 21 '13 at 19:26
  • Additional relevant pseudo-duplicates: [Reading small int with scanf](http://stackoverflow.com/q/9489210/1281433). – Joshua Taylor Aug 21 '13 at 19:29
  • 1
    @nishant `fscanf()` length modifiers: C11 7.21.6.2 11 "hh Specifies that a following d, i, o, u, x, X, or n conversion specifier applies to an argument with type pointer to signed char or unsigned char." Similar for `fprintf()`. I hope the doubt is lessened. – chux - Reinstate Monica Aug 21 '13 at 19:38
  • @chux : Thanks!! Got your point. – 0xF1 Aug 21 '13 at 19:41
  • 1
    @nishant: For `unsigned char`, use `%hhu` if you're treating the `unsigned char` as a small integer, so `"42"` gives you `(unsigned char(42)`. (FYI, in most of the English-speaking world, "doubt" is not synonymous with "question"; the word "doubt" implies disbelief.) – Keith Thompson Aug 21 '13 at 20:04

5 Answers5

8

You need to use int type in conjuction with %d specifier, and char with %c specifier. And %u with unsigned integers.

#include<stdio.h>
int main()
{
    unsigned int one=0; unsigned int two=0;
    printf("Quantity 1 = ");scanf("%u",&one);
    printf("Quantity 2 = ");scanf("%u",&two);
    printf("The value is %u",one);
    return 0;
}

Basicaly, scanf will try to read integer from input and it will try to store it inside memory location that is not large enough, so you will have undefined behavior.

You can find good reference here.

However, if you try to use character for an input type, you may want ask yourself why you won't get a chance to enter a second Quantity (if you type 4 and press enter). This is because second scanf will read enter key as a character. Also, if you try to type 21 (for a twentyone), it will fill the first value with 2 and second with 1 (well, with their ASCII values).

So, be careful - be sure that you always choose the right type for your variables.

Nemanja Boric
  • 21,627
  • 6
  • 67
  • 91
2

Never use scanf. Never use scanf. Seriously, never use scanf.

Use fgets (or getline, if you have it) to read an entire line of input from the user, then convert strings to numbers with strtol or its relatives strtod and strtoul. strsep may also be useful.

Community
  • 1
  • 1
zwol
  • 135,547
  • 38
  • 252
  • 361
  • 1
    @paulakis, there is nothing wrong with scanf, when used correctly. People get into trouble because they don't read its documentation. If your school assignment says use scanf then learn to use scanf it is a good exercise in reading documentation. – JackCColeman Aug 21 '13 at 21:23
  • @JackCColeman "Input overflow triggers undefined behavior" most definitely is a fault in (the specification of) scanf rather than the programmer, and the sheer difficulty of using it even vaguely correctly is also a fault in the spec IMNSHO. Don't blame the victim. – zwol Aug 22 '13 at 01:05
  • @Zack where does it say this? Nowhere. – JackCColeman Aug 22 '13 at 02:00
  • @JackCColeman C99 7.19.6.2p10: "If [the object that receives the result of scanning] does not have an appropriate type, or if *the result of the conversion cannot be represented in the object*, the behavior is undefined." Read, weep. – zwol Aug 22 '13 at 02:13
  • @zack, that is **NOT** the same as input overflow. – JackCColeman Aug 22 '13 at 03:36
  • @JackCColeman Produce text from the standard backing up your position. – zwol Aug 22 '13 at 12:53
  • @Zack, you have really pointed out what I think the real problem is. That is, people read the spec. as if it were a legal document. The problem is that there is no generally accepted interpretation of the standards. that is, there is no body of law, no litigation. So, we left to coding something that we believe meets the standard and then testing it. The compiler becomes the judge and jury! So, the clause you cite says basically, if the programmer does **not** code scanf correctly then it is allowed to produce a bug. – JackCColeman Aug 22 '13 at 18:04
  • @JackCColeman You would contend that `scanf("%u", &x);` (where `x` is in fact an `unsigned int`) is as correct a *use* of `scanf` as the application programmer can produce, yes? Well, assuming 32-bit or smaller `unsigned int`, that call exhibits undefined behavior if the text on standard input is "4294967296". – zwol Sep 04 '13 at 22:19
  • @JackCColeman (If by "if the programmer does not code scanf correctly", you meant that you would consider the *implementor of `scanf`* to have erred in producing an implementation that made demons fly out of your nose on the above example, well, I do not disagree, but application programmers are still screwed.) – zwol Sep 04 '13 at 22:21
  • if you found a bug in scanf report it to the compiler writers. Don't pick your nose, it releases demons. – JackCColeman Sep 04 '13 at 22:57
  • @JackCColeman Bugs in low-level system stuff only go away on a timescale of decades - I've been running compliance audits on system headers lately, and many recent systems *still* don't fully conform to POSIX.1-2001 and C99, both of which came out more than ten years ago! So even if you-the-application-programmer do report this (as poor QoI, I suppose) you still have to work around. Which brings us back to "don't use `scanf`". – zwol Sep 04 '13 at 23:20
  • @JackCColeman If you're comfortable with the possibility that your program might crash just because one of its users typed too many digits at it, who am I to tell you otherwise? – zwol Sep 05 '13 at 01:48
  • when my users are asked to enter a number between 0 and 10 they always enter 3949482002394857730234023992 – JackCColeman Sep 05 '13 at 15:48
  • @JackCColeman I suggest you read https://cubist.cs.washington.edu/Security/2007/11/22/why-a-computer-security-course-blog/ and https://www.schneier.com/blog/archives/2008/03/the_security_mi_1.html – zwol Sep 05 '13 at 17:11
1

Check if scanf() is working properly by reading its return value. For quickstart, read the details about scanf() at this link.

What you are doing is inputting a integer using "%d" into an unsigned char variable, therefore scanf() may not be working as it should.

0xF1
  • 6,046
  • 2
  • 27
  • 50
1

Change

unsigned char one=0; unsigned char two=0;

to

unsigned int one=0; unsigned int two=0;

and also use %u instead of %d then it will print the value after scanf().

haccks
  • 104,019
  • 25
  • 176
  • 264
1

You declared the variable one to be a char:

unsigned char one=0;

But then you told scanf to read an int:

scanf("%d",&one);  /* %d means int */

Int is bigger than char (typically 4-bytes vs. 1-byte), causing the problem you describe.

Change your scanf to:

scanf("%c",&one);  /* %c means char */

Then when you print out the value, also print a char:

printf("The value is %c",one); /* %c means char */
abelenky
  • 63,815
  • 23
  • 109
  • 159
  • I can't say whether it is relevant to @paulakis, as he is new to C, but is `scanf()` a good function to read `char` using `%c`? – 0xF1 Aug 21 '13 at 19:29