C fscanf отбрасывает лишние символы, если они есть - PullRequest
0 голосов
/ 27 марта 2011

Я работаю над этим проектом для одного из моих классов, и в нем говорится: «Откажитесь от всего после трехзначных символов до следующего символа новой строки или EOF».

Например, следующий пример будет тестовым файлом конфигурации:

119
3561234
263abc

Мне нужно сохранить первые три цифры в отдельных переменных, определенных как строка, столбец, значение (соответственно).

Код, который у меня есть, следующий:

/*
 * Read in the initial puzzle configuration.
 * Each line is 4 characters long:
 *   Row    as a character '0' .. '9'
 *   Column as character '0' .. '9'
 *   Digit  as character '0' .. '9'
 *   Terminating newline.
 * Exits with an error message if there are syntactic
 * or semantic errors with any configuration line.
 */

void configure(FILE *puzzle_file) {

    int row, column, value; // Variables
    int count = 1; //the counter for what line we are on 

    /*
     * Loops through every line transforming the chars to character int values
     * for each int needed and addes it to puzzle and changes fixed values
     * at same location.
     */
    while((fscanf(puzzle_file, "%1i%1i%1i%*[^\n]", &row, &column, &value)) != EOF){
            if(!in_range(row) || !in_range(column) || !in_range(value)){
                    printf("Illegal format in configuration file at line %i\n", count);
                    exit(1);
            }
            if(puzzle[row][column] != 0){
                    printf("Illegal placement in configuration file at line %i\n",count);
                    exit(1);
            }

            puzzle[row][column] = value;
            fixed[row][column] = 1;

            count++;
    }

}

Я ожидаю, что 9 будет идти в строке 1, а столбец 1, 6 - в строке 3 и столбце 5, а 3 - в строке 2 и столбце 6.

При правильном форматированном конфигурационном файле он перейдет в первый оператор if и закончится там.

Пример правильного файла конфигурации:

123
356
235
etc..

Я предполагаю, что мой fscanf заставляет его работать неправильно. Как бы вы изменили это, чтобы он это сделал?

РЕДАКТИРОВАТЬ 1:

функция in_range:

/*
 * Return TRUE iff the value is in the Sudoku range (1 .. 9)
 */
static bool in_range(int value) {

    if(isdigit(value) && value != 0){
            return TRUE;
    }
    return FALSE;
}

Ответы [ 2 ]

4 голосов
/ 27 марта 2011

Похоже, вы думаете, fscanf() использует регулярные выражения.

Это не так. C не имеет регулярных выражений.

Я думаю вы ищете:

fscanf(puzzle_file, "%1i%1i%1i%*s", &row, &column, &value)

При этом 1-й, 2-й и 3-й символы будут получены как целые числа, тогда оставшиеся данные в строке не будут сохранены в переменной.

Я никогда не видел [^/n] в scanf, и, видимо, это не проблема.

Я подозреваю, что проблема в вашей in_range() функции. Что это?

Редактировать, так как добавлен дополнительный код:

Ваш fscanf был в порядке. Ваш in_range() нет. isdigit() сообщает вам, является ли символ цифрой.

Перечитывая ваши требования, я предлагаю это для вашей логики чтения строк:

char buffer[5];
int row, column, value;
int count = 1;
while(fgets(buffer, 5, puzzleFile) != NULL)
{
    if ( (buffer[3] == '\n') 
          && (sscanf(buffer, "%1i%1i%1i%*[^\n]", &row, &column, &value) == 3))
    {
         puzzle[row][column] = value;
    }
    else
    {
          printf("Illegal format in configuration file at line %i\n", count);
          exit(1);
    }
    count++;

}

Это гарантирует, что каждая строка состоит из 3 символов с новой строкой. %1i в sscanf гарантирует, что каждый символ является цифрой в диапазоне 0-9, если все три соответствуют и были присвоены вашим переменным (он возвращает количество назначений).

1 голос
/ 27 марта 2011

Попробуйте прочитать строку за раз из файла в буфер, используя что-то вроде getline().Затем используйте

sscanf(buffer, "%1d%1d%1d", &row, &column, &value);

для сканирования значений в ваших переменных.

...