Сохранение строки из стандартного ввода никогда не меняется - PullRequest
0 голосов
/ 02 июня 2019

Я работаю над этой проблемой ( Uva227 ). Я почти получил правильные результаты при тестировании случаев, но столкнулся с проблемой.Я использовал функцию gets (), чтобы получить строку из стандартного ввода и сохранить ее в [0].но после первой входной матрицы a [0] больше не меняется.Что с ним не так?

PS В Puzzle # 2 (то есть во второй матрице ввода) a [0] не изменилось, поэтому я получил неправильный ответ.Но если я поставлю это первым, он вернет правильный вывод.Так что я думаю, что алгоритм правильный, но что-то пошло не так при чтении первой строки.

Английский не мой родной язык;прошу прощения за мои синтаксические ошибки.

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

char a[5][5];



int main(){
    int _case = 1;
    char c;
    while(gets(a[0])){//Please focus on this line;it seems that a[0] never changed since first reading.
        if(a[0][0] == 'Z')  break;
        int blank_i, blank_j;
        for(int i = 0; i < 5; i++){
            if(i)   gets(a[i]);
            for(int j = 0; j < 5; j++){
                if(a[i][j] == ' '){
                     blank_i = i;
                     blank_j = j;
                }
            }
        }
        bool flag = true;
        int i = 0;
        while((c = getchar()) != '0'){
            switch(c){
                case 'A':
                    a[blank_i][blank_j] = a[blank_i - 1][blank_j];
                    a[--blank_i][blank_j] = ' ';    break;
                case 'B':
                    a[blank_i][blank_j] = a[blank_i + 1][blank_j];
                    a[++blank_i][blank_j] = ' ';    break;
                case 'L':
                    a[blank_i][blank_j] = a[blank_i][blank_j - 1];
                    a[blank_i][--blank_j] = ' ';    break;
                case 'R':
                    a[blank_i][blank_j] = a[blank_i][blank_j + 1];
                    a[blank_i][++blank_j] = ' ';    break;
                default:    break;
             }
        }
        //add a getchar() here will fix the problem.
        printf("Puzzle #%d:\n", _case);
        if(blank_i < 0 || blank_i > 4 || blank_j < 0 || blank_j >  4)
             printf("This puzzle has no final configuration.\n");
        else{
            for(int i = 0; i < 5; i++){
                for(int j = 0; j < 5; j++){
                    printf("%c ", a[i][j]);
                }
            printf("\n");
            }
        }
        printf("\n");
        _case++;
    }
    return 0;
}

Ответы [ 2 ]

1 голос
/ 02 июня 2019

Вы ошиблись в диагностике проблемы.Дело не в том, что «после первой входной матрицы a [0] больше не меняется».Проблема в том, что после прочтения '0', заканчивающего список ходов, перед началом следующей головоломки появляется новая строка.Ваш код не принимает это во внимание и поэтому обрабатывает новую строку как первый символ первой строки следующей головоломки.Исправьте это, проглотив эту новую строку, прежде чем вернуться к началу цикла while.

В сторону: некоторые комментаторы указали, что вы не должны использовать gets.Они на 100% правы, но это не связано с этой проблемой, и переход от нее не исправит это.

0 голосов
/ 02 июня 2019

В дополнение к ответу Джозефа вы приглашаете Неопределенное поведение , так как не можете подтвердить, что ваши i, j, blank_i, blank_j индексы остаются в границах.(и * Никогда, никогда не используйте gets(), оно было удалено из текущего стандарта Си).См .: Почему get () настолько опасен, что его никогда не следует использовать!

Вместо этого используйте fgets и обрежьте конечный '\n' из полученной строки, перезаписав nul-characer , например,

#define ROWS 5      /* if you need a constant, #define one (or more) */
#define COLS ROWS

char a[ROWS][COLS];
...
        for(int i = 0; i < ROWS; i++){
            if (i)                                  /* skips a[0] */
                if (fgets (a[i], COLS, stdin))
                    a[i][strcspn(a[i], "\n")] = 0;  /* overwrite '\n' */
                else {  /* handle failed input */
                    fputs ("error: EOF encountered.\n", stderr);
                    return 1;
                }
           ...

Далее, в следующем цикле for вы назначаете blank_i = i; и blank_j = j;, например,

            for (int j = 0; j < COLS; j++){
                if(a[i][j] == ' ') {
                     blank_i = i;
                     blank_j = j;
                }
            }

Впоследствии вызатем увеличивайте a[blank_i++][blank_j]; и используйте blank_j-- и blank_j++ (вы также должны убедиться, что blank_i-- никогда не приведет к отрицательному значению).Чтобы избежать неопределенного поведения , вы должны проверить, что ваши индексы остаются в диапазоне.Например, взяв case 'B':, вы можете сделать что-то похожее на:

                case 'B':
                    {   /* create new block to allow variable declaration
                         * blank_i + 1 can exceed 4 invokding Undefined
                         * Behavior. You must validate/handle value.
                         */
                        int row = blank_i + 1 % ROWS;
                        a[blank_i][blank_j] = a[row][blank_j];
                        /* same with ++blank_i */
                        blank_i = (blank_i + 1) % ROWS;
                        a[blank_i][blank_j] = ' ';
                        break;  /* lines don't cost $, done hide break at end */
                    }

Поскольку вы зацикливаете while ((c = getchar()) != '0'), оба значения blank_i и blank_j могут превысить границы вашего массива или привести квызов отрицательного индекса неопределенное поведение - задолго до вашей проверки:

        printf("Puzzle #%d:\n", _case);
        if(blank_i < 0 || blank_i > 4 || blank_j < 0 || blank_j >  4)
             printf("This puzzle has no final configuration.\n");

Пройдите и исправьте свою индексацию (обрабатывая ее любым способом), чтобы убедиться, что ваши индексы остаются в пределахвашего массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...