std::ungetc
Определено в заголовке <cstdio> | ||
|---|---|---|
int ungetc( int ch, std::FILE *stream ); |
Если ch не равно EOF, помещает символ ch (переинтерпретированный как unsigned char) в буфер ввода, связанный с потоком stream таким образом, что последующая операция чтения из stream извлечёт этот символ. Внешнее устройство, связанное с потоком, не изменяется.
Операции перемещения потока std::fseek, std::fsetpos, и std::rewind отбрасывают эффекты ungetc.
Если ungetc вызывается более одного раза без промежуточных операций чтения или перемещения, она может завершиться неудачно (другими словами, гарантируется буфер сброса размером 1, но буфер большего размера определяется реализацией). Если несколько успешных вызовов ungetc были выполнены, операции чтения извлекают сброшенные символы в обратном порядке их ungetc.
Если ch равно EOF, операция завершается неудачно, и поток не затрагивается.
Успешный вызов ungetc очищает флаг конца файла std::feof.
Успешный вызов ungetc для двоичного потока уменьшает указатель позиции потока на единицу (поведение неопределённо, если указатель позиции потока был равен нулю).
Успешный вызов ungetc для текстового потока изменяет указатель позиции потока неопределённым способом, но гарантирует, что после извлечения всех сброшенных символов операцией чтения, указатель позиции потока будет равен своему значению до ungetc.
Параметры
| ch | - | символ, который должен быть помещён в буфер ввода потока |
| stream | - | поток файла, в который должен быть возвращён символ |
Значение результата
При успехе возвращается ch.
При неудаче возвращается EOF и заданный поток остаётся неизменным.
Примечания
Размер буфера сброса на практике варьируется от 4k (Linux, MacOS) до всего 4 (Solaris) или гарантированного минимума 1 (HPUX, AIX).
Кажущийся размер буфера сброса может быть больше, если символ, который сбрасывается, равен символу, существующему в этом месте во внешней последовательности символов (реализация может просто уменьшить указатель позиции чтения файла и избежать поддержания буфера сброса).
Пример
демонстрирует использование std::ungetc в его первоначальной цели: реализации std::scanf
#include <cctype>
#include <cstdio>
void demo_scanf(const char* fmt, std::FILE* s)
{
while (*fmt != '\0') {
if (*fmt == '%') {
switch (*++fmt) {
case 'u': {
int c{};
while (std::isspace(c=std::getc(s))) {}
unsigned int num{};
while (std::isdigit(c)) {
num = num*10 + c-'0';
c = std::getc(s);
}
std::printf("%%u scanned %u\n", num);
std::ungetc(c, s);
break;
}
case 'c': {
int c = std::getc(s);
std::printf("%%c scanned '%c'\n", c);
break;
}
}
} else {
++fmt;
}
}
}
int main()
{
if (std::FILE* f = std::fopen("input.txt", "w+")) {
std::fputs("123x", f);
std::rewind(f);
demo_scanf("%u%c", f);
std::fclose(f);
}
}Вывод:
%u scanned 123 %c scanned 'x'
См. также
| получает символ из потока файла (функция) |
|
C документация для ungetc |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/io/c/ungetc