3

Code:

#include <stdio.h>


 int main(){

    int num;

    scanf("%d", &num);
    printf("Enter: ");

    char nums[5][num], ch;

    for(int i = 0; i < num; i++){
        for(int j = 0; j < 5; j++){
            if((ch = getchar()) != '\n'){
                nums[j][i] = ch;
            }
        }
    }


    for(int i = 0; i < num; i++){
        for(int j = 0; j < 5; j++){
            printf("%c ", nums[j][i]);
        }
        printf("\n");
    }

    return 0;
 }

Output:

1
Enter: 12345
 1 2 3 4 

Process returned 0 (0x0)   execution time : 6.282 s
Press ENTER to continue.

Why the last element is missing and the additional space at the beginning of the output of array?

If I change the range for j in both for loops to

j <= 5

then, the output looks like this:

1
Enter: 12345
 1 2 3 4 5 

Process returned 0 (0x0)   execution time : 2.107 s
Press ENTER to continue.

If the initial value for j is 1 in the printf loop, then the output looks like this:

1
Enter: 12345
1 2 3 4 5 

Process returned 0 (0x0)   execution time : 3.675 s
Press ENTER to continue.

No extra gap at the beginning of the array output.

Can anyone explain this and how to resolve this problem?

sarwar47
  • 174
  • 1
  • 1
  • 9
  • 2
    Your first `getchar` is consuming the newline character that `scanf` left behind. Replace that with `scanf("%d ", &num);` (note the whitespace). – Eugene Sh. Feb 11 '20 at 19:23
  • 1
    In general, you should avoid using `scanf` with other input methods. If you use `scanf` to read the number (using `"%d"`), then you should use `scanf` to read the characters (using `" %c"`). Note the space before the `%c`. – user3386109 Feb 11 '20 at 19:48
  • 2
    @EugeneSh. Trailing space in scanf is a bad idea, it means input will block until they type another non-whitespace item – M.M Feb 11 '20 at 21:51
  • 1
    Normally, in C, if you have a 2D array `SomeType array[5][num];`, your loops will work on the leading index before the trailing index: `for (int i = 0; i < 5; i++) { for (int j = 0; j < num; j++) { …array[i][j]… }`, but you have the code works with the indexes the other way around — so you fill columns rather than rows. That isn't automatically wrong, but it is aconventional in C (albeit the way Fortran works). You can look up 'column-major' and 'row-major' indexing — see Wikipedia on [Row-Major and Column-Major Order](https://en.wikipedia.org/wiki/Row-_and_column-major_order), for example. – Jonathan Leffler Feb 12 '20 at 02:54

2 Answers2

4

The problem is that the function getchar reads all characters from the input stream including the new line character that stored in the buffer after the first call of scanf.

So in the loops the first character that is read is the new line character '\n'. You should remove it for example the following way.

scanf( "%*[^\n]" );
scanf( "%*c" );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Another method, though not as elegant, would be to add something like `while(getchar() != '\n') continue;` after `scanf`. – Fiddling Bits Feb 11 '20 at 19:26
  • 3
    @FiddlingBits although you should also check for EOF – M.M Feb 11 '20 at 21:51
  • in other words, the first call to scanf is reading char "1" and there is \n lurking in the input buffer. next, you start calling getchar(), so you get `\n 1 2 3 4` so these are your 5 elements that you are reading. The '5' one would not be read since you hardcoded 5 calls to getchar() – Kobi Feb 12 '20 at 00:20
1

You have a logic issue in the first loop. You test for \n but then if you do find a \n, you leave the array entry uninitialized and go on to the next entry anyway. This leads to the bogus output.

Instead you could delay the j++ until getting a valid character, e.g. :

for(int i = 0; i < num; i++){
    for(int j = 0; j < 5;     ){
        if((ch = getchar()) != '\n'){
            nums[j][i] = ch;
            ++j;
        }
    }
}

Then the array will be filled with the non-newline characters that get entered, and you don't need to do any other flushling.

It would improve the code to also check ch != EOF (and ch should be declared as int), but then you will need some error handling (it would be a mistake to just break the loop and go on to try and output the whole array).

M.M
  • 138,810
  • 21
  • 208
  • 365