2

So I've just started learning C for a class of mine, and I have been working on this assignment, but this part has me perplexed. I have some code that essentially looks like:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int one = 0;
    int two = 0;
    char oneWord[100]; 
    char twoWord[100];

    printf("Enter a two digit number: ");
    scanf("%d%d", &one, &two);

    strcpy(firstWord, "Test");
    strcpy(secondWord, "Two");

    printf("%s", firstWord);

    return 0;
}

Now, logic/purpose of the program aside, what I cannot figure out is why that scanf statement is resulting in an infinite loop? I determined that was that cause of the problem when I commented it out and the final printf statement worked just fine.

I tried changing it to scanf("%d,%d", %one, %two) and that seemed to work fine when I added a comma to the input. But I want to just be able to take a number like 55 and break it into 2 digits. What exactly am I doing wrong here?

This 0ne Pr0grammer
  • 2,632
  • 14
  • 57
  • 81

3 Answers3

7

What you run into is not an infinite loop, but rather scanf waiting for more input.

The d-format-specifier means a decimal number, so anything like "0", "41", or "2342345".

After you have entered the first number, you expect the program to continue, but scanf has just completed the first %d, so scanf is waiting for you to fulfill the second %d. This is what seems to you an infinite loop, but really is scanf doing what you ordered it to.

scanf cannot guess how many digits for each number you desire. But you can tell it how you want it, with a width-specifier that tells how many characters each information is composed of:

#include <stdio.h>

int main () {
    int a, b;
    scanf("%2d%1d", &a, &b);
    printf("%d, %d", a, b);
} 

with error handling:

#include <stdio.h>

int main () {
    int a, b;
    if (scanf("%2d%1d", &a, &b) < 2)
        fprintf(stderr, "not enough digits");
    else
        printf("%d, %d", a, b);
}
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • 3
    Also tell him that it is not infinite loop. instead it is waiting for just one more number to be entered. – Niraj Nawanit Oct 07 '12 at 08:35
  • Ah man, didn't expect so many answers this fast! But what I ended up doing was `scanf("%1d%1d", &one, &two)`, is there any problem with doing that as opposed to your solution of `scanf("%2d%1d", &one, &two)`? – This 0ne Pr0grammer Oct 07 '12 at 08:38
  • 1
    @This0nePr0grammer: You must understand what the digit before the `d` means: It is the number of digits to parse, so for "%3d" and the number "123456", `scanf` would give you "123". Now you should be able to answer your question yourself. – Sebastian Mach Oct 07 '12 at 08:40
  • 1
    @This0nePr0grammer Welcome :) (edit: added a more detailed explanation for the "infinite loop") – Sebastian Mach Oct 07 '12 at 08:45
2

I might be wrong, but %d means "an integer", not "a digit". So 55 is the first %d, then the second one isn't defined.

You could try with %c (one char).

Cyrille
  • 25,014
  • 12
  • 67
  • 90
  • 1
    You are probably right. See [this](http://www.cplusplus.com/reference/clibrary/cstdio/scanf/) for reference, but doesn't completely answer his question. – Ozair Kafray Oct 07 '12 at 08:33
  • 1
    Also tell him that it is not infinite loop. instead it is waiting for just one more number to be entered. – Niraj Nawanit Oct 07 '12 at 08:33
  • 1
    To be more precise, "d" is for "decimal", meaning a "decimal number", in other words, a base 10 number. – Sebastian Mach Oct 07 '12 at 08:45
1
printf("Enter a two digit number: ");
scanf("%1d%1d", &one, &two);

Of course even this can fail (not meet the requirements)
Instead:

scanf("%d", &one);
if (one<10 || one>99) printf("I didn't expect that...\n");

or

scanf("%s",oneWord); one = atoi(oneWord);
if (one<10 || one>99)
   printf("Thats not necessarily even a number\n");
else
   { two = one % 10; one = one / 10; 
       printf("The first digit is %d and the second is %d\n",one,two);
   }

In the latter program we are testing that the input is correct:
It's a good practice to feed garbage instead of the correct input and see, where it goes unnoticed. The library function atoi(string); returns an integer contained in a string. It's zero, if no integer was found. e.g. (atoi("a1") == 0).

But the minimum correct answer would be

scanf("%d", number);
if (number >= 10 && number <= 99) 
{
   one = number / 10;  // the first digit;
   two = number % 10;  // the second digit calculated as number modulo 10
}

scanf("%1d%d", &one, &two);  // would halt for a single character input
Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
  • 1
    if `one` is a single, decimal (as in "d") digit, then how could it be bigger than 9? And an error check that is itself unsure about what it does is not a valid error check. – Sebastian Mach Oct 07 '12 at 08:43
  • 1
    Try the first example and enter e.g. 123; it's not a two digit number. – Aki Suihkonen Oct 07 '12 at 08:45
  • I missed that you don't use a width-specifier in your second format string (unlike in the first format string). However, it wouldn't solve the questioners problem of dissecting a number string into several numbers. Also: Your second example goes a bit too far for the problem at hand. Maybe at least explain what you are doing there? – Sebastian Mach Oct 07 '12 at 08:50