2

I want to type in a number that is 10 digits long, then put the digits into an array. But for some reason, I get this random 2-digit numbers that seem to have nothing to do with my input (??).

char number[10];            //number containing 10 digits
scanf("%s",number);         //store digits of number
printf("%d\n",number[0]);   //print the 1st digit in the number
printf("%d\n",number[1]);   //print the 2nd digit in the number

Here is what I got:

Input:
1234567890

Output:
49
50

Actually, 49 should be 1, and 50 should be 2.

carljalal
  • 637
  • 6
  • 16
  • You are printing the character `'1'` as integer by specifying `%d` as the format specifier. `'1'` has integer code of 48. Similarly `'1'` has an integer code of 49. If you want to print the character `'1'` as a character you should use `%c` as the format specifier. – Susam Pal Apr 10 '14 at 11:52
  • So if my characters `0~9` are actually numbers `48~57`... all I need to do is subtract `48` from the character to get the number? – carljalal Apr 10 '14 at 12:30
  • No! Like I have already mentioned in my answer, you should not rely on those numbers. Those numbers are not guaranteed to be same in all implementations of the C compiler. – Susam Pal Apr 10 '14 at 12:46
  • So can I reliably convert the char to int with `- '0' ` ? – carljalal Apr 10 '14 at 14:34
  • @user3400450 Yes. `digit = ch - '0'` will covert `ch` values `'0'`, to `'9'` to `digit` values `0` to `9` with any conforming character encoding like ASCII. The integer type of `digit` and `ch` are irrelevant. – chux - Reinstate Monica Apr 10 '14 at 14:42

5 Answers5

3

You are getting ASCII value of characters 1 and 2. Use %c specifier to print the digits.

printf("%c\n",number[0]);
haccks
  • 104,019
  • 25
  • 176
  • 264
2

Warning! Your code may invoke undefined behaviour!

But we'll talk about it later. Let us address your actual question first.

Here is a step by step explanation of what is going on. The first thing you need to know is that every character literal in C is actually an integer for the compiler.

Try this code.

#include <stdio.h>

int main()
{
    printf("%d\n", sizeof '1');
    return 0;
}

The output is:

4

This shows that the character literal '1' is represented as 4 byte integer by the compiler. Now, let us see what this 4 byte integer for '1' is using the next code here.

#include <stdio.h>

int main()
{
    int a = '1';
    printf("a when intepreted as int : %d\n", a);
    printf("a when intepreted as char: %c\n", a);
    return 0;
}

Compile it and run it. You'll see this output.

a when intepreted as int : 49
a when intepreted as char: 1

What do we learn?

The character '1' is represented as the integer 49 on my system. This is so for your system too. That's because in my system as well as yours, the compiler is using ASCII codes for the integers where '1' is 49, '2' is 50, 'A' is 65, 'B' is 66, and so on. Note that the mapping of the characters to these codes could be different for another system. You should never rely on these integer codes to identify the characters.

So when I try to print this value as integer (using %d as the format specifier), well what gets printed is the integer value of '1' which is 49. However, if we print this value as a character (using %c as the format specifier), what gets printed is the character whose integer code is 49. In other words, 1 gets printed.

Now try this code.

#include <stdio.h>

int main()
{
    char s[] = "ABC123";
    int i;
    printf("char  %%d  %%c\n");
    printf("----  --  --\n");
    for (i = 0; i < 6; i++) {
        printf("s[%d]  %d  %c\n", i, s[i], s[i]);
    }
    return 0;
}

Now you should see this output.

char  %d  %c
----  --  --
s[0]  65  A
s[1]  66  B
s[2]  67  C
s[3]  49  1
s[4]  50  2
s[5]  51  3

Does it make sense now? You need to use the %c format specifier when you want to print the character. You should use %d only when you want to see the integer code that represents that character.

Finally, let us come back to your code. This is how you fix it.

#include <stdio.h>

int main()
{
    char number[10];
    scanf("%9[^\n]", number);
    printf("%c\n", number[0]);
    printf("%c\n", number[1]);
    return 0;
}

There are two things to note.

  • I have used %c as the format specifier to print the character representation of the digits read.
  • I have altered the format specifier for scanf to accept at most 9 characters only where the characters are not newline characters. This is to make sure that a user cannot crash your program by inputting a string that is far longer than 9 characters. Why 9 instead of 10?. Because we need to leave one cell of the array empty for the null-terminator. A longer input would overwrite memory locations beyond the allocated 10 bytes for the number array. Such buffer overruns lead to code that invoke undefined behaviour which could either cause a crash or kill your cat.
Community
  • 1
  • 1
Susam Pal
  • 32,765
  • 12
  • 81
  • 103
0
printf("%c\n",number[0]);   //print the 1st digit in the number
printf("%c\n",number[1]);   

should do the job for you, what you see are ascii values.

Smitt
  • 178
  • 7
0

your number array is an array of char, and so every element of it is a char. when you type:
printf("%d\n",number[0]);
you printing the chars as integers, and so you get the ASCII code for each char.

change your statement to printf("%c\n",number[0]); to print chars as chars not as ints

Moha the almighty camel
  • 4,327
  • 4
  • 30
  • 53
-3

Warning! Your code invokes undefined behaviour!

char number[10];     // Can only store 9 digits and nul character
scanf("%s",number);  // Inputting 1234567890 (11 chars) will overflow the array!

Use fgets instead:

#define MAX_LEN 10
char number[MAX_LEN];
if(fgets(number, MAX_LEN, stdin)) {
     // all went ok
}

Once you have fixed this, you can fix the printing problem. You are printing the character code (number), and not the actual character. Use different type specifier:

printf("%c\n",number[0]);
Community
  • 1
  • 1
user694733
  • 15,208
  • 2
  • 42
  • 68
  • 2
    This answer is factually correct but doesn't answer the question at all. – Susam Pal Apr 10 '14 at 12:09
  • @SusamPal Actually it does. If there is UB in your code, then any other fixes are meaningless. – user694733 Apr 10 '14 at 12:10
  • 1
    I agree with your comment just like I agree with your answer. However, the OP has a specific question: Why does he get `49` in the output when he expects `1`? The answer is not: "due to undefined behaviour". The answer is "incorrect use of format specifier". – Susam Pal Apr 10 '14 at 12:14
  • @SusamPal Except that output *can* still be `49` because of the UB. But anyway, added the stuff about the `printf`. – user694733 Apr 10 '14 at 12:22
  • It _can_ be but it _is not_. – Susam Pal Apr 10 '14 at 12:23
  • @SusamPal How can you be sure? UB by definition does not work reliably. OP does not specify the environment the code runs in, and because of that we should not make any assumptions on how UB works. – user694733 Apr 10 '14 at 12:25
  • By reasonable assumptions, disassembling or by using `gcc -S` or its equivalent for your compiler. I am assuming the OP is not using an arcane implementation which is mysteriously printing `49` due to undefined behaviour. I would like to know one implementation you are aware of which exhibits such behaviour on undefined behaviour. – Susam Pal Apr 10 '14 at 12:39
  • @SusamPal I agree with you that the actual behaviour experienced by the OP, is not likely by UB. But when UB is involved, code is broken. Period. And that should be the **first** thing that is fixed. Everything else is secondary. – user694733 Apr 10 '14 at 12:47
  • @user694733 I agree. Your concern is valid and your post should have been a comment to the question, not a separate answer. The question is concerned with the `49` in the output. The accepted answer addresses this as well UB. Your answer does not address the question. Hence, you have been downvoted. Please live with it and stop this discussion here. – Susam Pal Apr 10 '14 at 12:54