3

I am trying to use getchar() to read all the digits of an input number and store them in an array. But every time I run the program something goes wrong with the second digit.

Here is my code:

int ch = 0;
int digits[0];
int i = 0;

while ((ch = getchar()) != '\n') {
    digits[i] = ch - '0';
    i++;
}

To show what will go wrong, I inserted two printf:

while ((ch = getchar()) != '\n') {
    printf("%d ", ch);
    digits[i] = ch - '0';
    printf("%d\n", ch);
    i++;
}

For example, when I input 1100, I get:

49 49

49 1

48 48

48 48

And when I print the array in a separate loop, the output is:

1 10 0 0

When I input 66666, I get:

54 54

54 6

54 54

54 54

54 5

And the array is:

6 10 6 6 6

I've tried a bunch of other numbers with different lengths, every time the same weird thing happens with the second digit, and only the second. Does anyone know why's that? Thanks a lot!

Community
  • 1
  • 1
yixiaoyx
  • 63
  • 6

4 Answers4

10
int digits[0];

You have an array which holds zero digits.

int digits[32];     /* or some reasonable size, check for overflow... */
John Hascall
  • 9,176
  • 6
  • 48
  • 72
  • This does not answer the question. It just tells them how to fix the problem, not *why* this is happening, what was actually asked. – Hermann Döppes Aug 21 '16 at 14:59
6

As has been pointed out two times already, your array has size zero and can therefore not hold all the numbers you tried to shove in there.

Thus, when writing to any position in the array, you are actually writing to memory that is used for other stuff, like holding ch, for example. Apparently it just so happens that the place where your program expects (the inexistent) digits[1] to be, ch is stored. Hence you are overwriting ch with ch - '0'.

Then, when leaving the scope of ch, the program is free to write other stuff there. (Because obviously the memory is not needed anymore.) Apparently it decides to write something that has value 10. This leads to the “strange” output.

Note that writing and reading outside the bounds of an array is undefined behaviour and can have much worse side effects than this one. Try to avoid it in the future.

Hermann Döppes
  • 1,373
  • 1
  • 18
  • 26
  • You indeed answered my question, thank you. If I could accept two answers it would be yours and the one I chose now :) – yixiaoyx Aug 23 '16 at 10:52
4

every time I run the program something goes wrong with the second digit.

This is because you have declared your array digit as zero-size array and the compiler doesn't allocate any memory for your array. Thus, writing to any position in the array will actually write to memory locations allocated for other purposes (like allocated for other variables) and also, it will have undefined behavior.

So, the result you were getting is due to that UNDEFINED BEHAVIOR and in your case, writing to any position using indices with digit is actually writing to memory allocated to other variables in your program and the memory location you get by digit[1] happens to be memory location allocated to variable ch of type char in your program. Hence, writing to memory location digit[1] will modify your ch variable. Since, it is undefined behavior, you may get a Segmentation Fault for your program.

To solve your problem, declare array digit to be of sufficient size.

#define SIZE_DIGITS  /* Sufficient Size required by your application */
int digit[SIZE_DIGITS];

However, in Standard C and C++, zero-size array is not allowed and if you're using GCC, compile it with -pedantic option. It will give warning, saying:

zero.c:3:6: warning: ISO C forbids zero-size array 'a' [-pedantic]

In case of C++, it gives similar warning.

Also, zero-size arrays are very useful as the last element of a structure that is really a header for a variable-length object. They are allowed in GNU C.The structure having zero-size array as last element is called variable-length structure. You can read more about it here.

abhiarora
  • 9,743
  • 5
  • 32
  • 57
3

There are a number of little problems with the posted code:

  1. array digits[] is set to 0 size, so cannot hold any digits so trying to place anything in digits[x] corrupts the stack

  2. the while() loop, even if the digits[] were properly declared, will not stop inputting characters (as long as not EOF and not newline) so can overrun any array size

  3. the posted code does not watch for a EOF condition

here is some code that will work correctly and only allows a max of 32 digits

#include <stdio.h>

#define MAX_DIGITS (32)

int main( void )
{

    int ch = 0;
    int digits[ MAX_DIGITS ];


    int i = 0;
    while ( i < MAX_DIGITS && ( (ch = getchar()) != EOF && '\n' !=  ch) ) 
    {
        printf("%d ", ch);
        digits[i] = ch - '0';
        printf("%d\n", digits[i]);
        i++;
    }
}

here is a sample input

1 2 3 4 5 6

and the resulting output

49 1
32 -16
50 2
32 -16
51 3
32 -16
52 4
32 -16
53 5
32 -16
54 6

Note: the 32 -16 is from the spaces in the input, so for best results, code should be modified to ignore other than digit input

user3629249
  • 16,402
  • 1
  • 16
  • 17
  • @chux, There is always the possibility that I was looking at MY first write of the `while()` statement with the additional check of the EOF condition. I'll edit my answer to remove the current #3 – user3629249 Aug 22 '16 at 15:39
  • Thanks, your answer is also very helpful. – yixiaoyx Aug 23 '16 at 10:40