0

I am working on a code, and I tried to enter a char instead of integer, and the result was '2' regardless of the character I entered, is it undefined behaviour or some thing else ?

The code:

#include <stdio.h>
int f1(int n);
int f2(void);

int main(void)
{
    int t;

    printf("Enter a number: ");
    scanf("%d", &t);
    /* print proper message */
    t ? f1(t) + f2() : printf("zero entered.\n");
    return 0;
}

int f1(int n)
{
    printf("%d ", n);
    return 0;
}

int f2(void)
{
    printf("entered.\n");
    return 0;
}

when I entered a, the result was "2 entered", and when I entered g the result was "2 entered" and when I entered i,h,k,..... the result was the same. What is that?

Pierre Fourgeaud
  • 14,290
  • 1
  • 38
  • 62
Armia Wagdy
  • 567
  • 6
  • 22
  • 2
    What's the point of the addition : `f1(t) + f2()` ? – Michael M. Aug 18 '13 at 09:29
  • @Michael concatenate the output on the screen... – A4L Aug 18 '13 at 09:30
  • 1
    @A4L Uh... that's not how it works. – thejh Aug 18 '13 at 09:32
  • Here, `f1(t)+f2()` should at least be replaced with `f1(t),f2()`. Even more clear would be an `if` statement: `if (t) { f1(t); f2(); } else { printf("zero entered.\n"); }` – thejh Aug 18 '13 at 09:34
  • @thejh it's `0 + 0` and the side effect are the two `printf`s in `f1` and `f2` witch then look like `"2 entered"` ... that's a weird way of writing a message anyways ... – A4L Aug 18 '13 at 09:34
  • @A4L, this will only add returned values (`0` in both functions) and not use the result... Anyway, use `scanf("%c", &t)` instead of `scanf("%d", &t)` – Michael M. Aug 18 '13 at 09:36
  • @A4L Yes, I understand that. However, I think that `+` should be avoided here because you're not using the result, and so it just makes the code unclear. – thejh Aug 18 '13 at 09:36
  • This code does not have any rhyme or reason. – Ed Heal Aug 18 '13 at 09:37
  • I am totally agreed with @thejh – Michael M. Aug 18 '13 at 09:38
  • @Michael I agree too, `+` is just misleading makes no sense in this case. – A4L Aug 18 '13 at 09:43
  • this code explains that The use of the ? operator to replace if-else statements is not restricted to assignments only. this code is from c++ the complete reference by Herbert Schildt – Armia Wagdy Aug 18 '13 at 09:45
  • @ArmiaWagdy: In all seriousness, you should [absolutely avoid any books by Schildt](http://stackoverflow.com/questions/803522/after-kr-what-book-to-use-to-learn-programming-in-plain-c/803554#803554)... – Oliver Charlesworth Aug 18 '13 at 09:47
  • @ArmiaWagdy - Do you have a shredder - it needs feeding - why not give it that book – Ed Heal Aug 18 '13 at 09:50

5 Answers5

3

If scanf() encounters something it cannot parse based on the specified format string, it simply stops and returns early. So it never writes anything to t (you're just seeing whatever indeterminate value t had before the call).

To handle this, you should always examine the return value of scanf.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
0

The problem is, as you say, that scanf using %d format is expecting you to enter one or more ascii digits. It stops scanning the input at a non-digit character, so it never reads what you type and t has whatever value it had before the scant was called.

David Elliman
  • 1,379
  • 8
  • 15
0

You need to check the return code of scanf. Have a look at the manpage:

Return Value

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.

In other words, scanf does not write anything into t, it's uninitialized the whole time.

So, instead of this:

scanf("%d", &t);

try this:

int items_matched = scanf("%d", &t);
if (items_matched != 1) {
    printf("bad number entered\n");
    exit(1);
}
Community
  • 1
  • 1
thejh
  • 44,854
  • 16
  • 96
  • 107
0

It is because scanf failed to parse you input. It expects you to enter a decimal digits since you used %d.

You have to check the return value of scanf to avoid this kind of behavior :

On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.

So :

int items_matched;

// ...
items_matched = scanf("%d", &t);   // Get the return value

if ( items_matched != 1 )          // Check it
{
    printf("Matching failure with scanf.\n");
    return 0;
}
else
{
    if ( t == 0 )
        printf("zero entered\n");
    else
        printf("%d entered\n", t);
}

You don't need your f1(t) + f2() who is quite confusing...

Pierre Fourgeaud
  • 14,290
  • 1
  • 38
  • 62
  • Did you mean that if the code was :#include int main(void){ int t,m; int items_matched; // ... printf("Enter two numbers : "); items_matched = scanf("%d,%d", &t,&m); // Get the return value if ( items_matched != 2 ) // Check it { printf("Matching failure with scanf.\n"); return 0; } else { if ( t == 0 ) printf("zero entered\n"); else printf("%d entered\n", t); } } – Armia Wagdy Aug 18 '13 at 10:00
  • actually An Int and Char can be interexchanged.. 'A' == 65 – Joe DF Aug 18 '13 at 11:28
  • @JoeDF Yes that is true. I edited my answer for something better. Thanks for pointing this out ! – Pierre Fourgeaud Aug 18 '13 at 12:41
0

From the Linux man page

The format string consists of a sequence of directives which describe how to process the sequence of input characters. If processing of a directive fails, no further input is read, and scanf() returns. A "failure" can be either of the following: input failure, meaning that input characters were unavailable, or matching failure, meaning that the input was inappropriate.

In the C11 standard description of scanf (7.21.6.4 The scanf function) section 3:

The scanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

Emphasis is mine . So as @oli charlesworth said you should check the return value of scanf when in doubt :)

0decimal0
  • 3,884
  • 2
  • 24
  • 39