Последний элемент отсутствует в массиве 2D - PullRequest
3 голосов
/ 11 февраля 2020

Код:

#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;
 }

Вывод:

1
Enter: 12345
 1 2 3 4 

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

Почему отсутствует последний элемент и дополнительное пространство в начале вывода массива?

Если я изменю диапазон для j в обоих циклах на

j <= 5

, то результат будет выглядеть следующим образом:

1
Enter: 12345
 1 2 3 4 5 

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

Если начальное значение для j равно 1 в printf l oop, тогда выходные данные выглядят так:

1
Enter: 12345
1 2 3 4 5 

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

Нет дополнительного пробела в начале вывода массива.

Кто-нибудь может объяснить это и как решить эту проблему?

Ответы [ 2 ]

4 голосов
/ 11 февраля 2020

Проблема в том, что функция getchar читает все символы из входного потока, включая символ новой строки, который сохраняется в буфере после первого вызова scanf.

Так что в циклах первый прочитанный символ - это символ новой строки '\n'. Вы должны удалить его, например, следующим образом.

scanf( "%*[^\n]" );
scanf( "%*c" );
1 голос
/ 12 февраля 2020

У вас проблема с логикой c в первом l oop. Вы проверяете на \n, но затем, если вы найдете \n, вы оставляете запись массива неинициализированной и в любом случае go переходите к следующей записи. Это приводит к фиктивному выводу.

Вместо этого вы можете отложить j++ до получения действительного символа, например:

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

Тогда массив будет заполнен не-символами новой строки которые вводятся, и вам не нужно делать никаких других сбросов.

Это улучшило бы код и для проверки ch != EOFch должно быть объявлено как int), но тогда вы потребуется некоторая обработка ошибок (было бы ошибкой просто разбить l oop и go на, чтобы попытаться вывести весь массив).

...