ungetc: количество байтов pushback - PullRequest
4 голосов
/ 19 октября 2011

ungetc гарантирует только один байт возврата. С другой стороны, я протестировал его на Windows и Linux, и он работает с двумя байтами.

Существуют ли какие-либо платформы (например, какие-либо текущие системы Unix), на которых он фактически занимает всего один байт?

Ответы [ 3 ]

6 голосов
/ 19 октября 2011

Стандарт C99 (и стандарт C89 до этого) однозначно сказал:

Один символ отталкивания гарантирован. Если функция ungetc вызывается слишком много раз в том же потоке без промежуточной операции чтения или позиционирования файла на этом поток, операция может завершиться неудачей.

Таким образом, чтобы быть переносимым, вы не должны предполагать более одного символа возврата.

Сказав, что на MacOS X 10.7.2 (Lion) и RHEL 5 (Linux, x86 / 64) я попытался:

#include <stdio.h>
int main(void)
{
    int i;
    for (i = 0; i < 4096; i++)
    {
        int c = i % 16 + 64;
        if (ungetc(c, stdin) != c)
        {
            fprintf(stderr, "Error at count = %d\n", i);
            return(1);
        }
    }
    printf("No error up to count = %d\n", i-1);
    return(0);
}

У меня нет ошибок ни на одной платформе. Напротив, в Solaris 10 (SPARC) я получил сообщение об ошибке «count = 4». Хуже того, в HP-UX 11.00 (PA-RISC) и HP-UX 11.23 (Itanium) я получил ошибку при 'count = 1', опровергающую теорию о том, что 2 безопасно. Точно так же AIX 6.0 выдал ошибку при 'count = 1'.

Резюме

  • Linux: большой (4 КиБ)
  • MaxOS X: большой (4 КиБ)
  • Солярис: 4
  • HP-UX: 1
  • AIX: 1

Таким образом, AIX и HP-UX допускают только один символ pushback для входного файла, для которого не было прочитано никаких данных. Это неприятный случай; они могут обеспечить гораздо большую емкость отката после считывания некоторых данных из файла (но простой тест на AIX, добавляющий getchar() до того, как цикл не изменил емкость отката).

4 голосов
/ 02 октября 2014

Здесь есть несколько сообщений, предлагающих, что имеет смысл поддерживать 2 символа ради scanf.

Я не думаю, что это правильно: scanf нужен только один, и это действительно причина ограничения. Первоначальная реализация (еще в середине 70-х годов) поддерживала 100, и в руководстве было примечание: в будущем мы можем принять решение о поддержке только 1, так как это все, что нужно для scanf. См. Стр. 3 оригинального руководства (Возможно, не оригинальное, но довольно старое.)

Чтобы более ясно увидеть, что scanf требуется только 1 символ, рассмотрите этот код для функции %u scanf.

int c;
while isspace(c=getc()) {} // skip white space
unsigned num = 0;
while isdigit(c)
    num = num*10 + c-'0',
    c = getc();
ungetc(c);

Здесь нужен только один вызов ungetc(). Нет никаких причин, по которым scanf нужен только один символ: он может поделиться с пользователем.

3 голосов
/ 19 октября 2011

Реализации, которые поддерживают 2 символа возврата, вероятно, делают это для того, чтобы scanf мог использовать ungetc для своего возврата, вместо того, чтобы требовать второй почти идентичный механизм. Для программиста приложения это означает, что даже если вызов ungetc дважды кажется работающим, он может быть ненадежным во всех ситуациях - например, если последняя операция в потоке была fscanf, и ему пришлось используйте pushback, вы можете, вероятно, только ungetc один символ.

В любом случае непереносимо полагаться на более чем один символ возврата ungetc, поэтому я настоятельно рекомендую не писать код, который нуждается в этом ...

...