Бьерн Страуструп.
Язык программирования С++
262
В качестве альтернативы можно использовать функции get():
class istream : public virtual ios {
//...
istream& get(char& c); //
символ
istream& get(char* p, int n, char ='n'); //
строка
};
В них обобщенный пробел рассматривается как любой другой символ и они предназначены для таких
операций ввода, когда не делается никаких предположений о вводимых символах.
Функция istream::get(char&) вводит один символ в
свой параметр. Поэтому программу посимвольного
копирования можно написать так:
main()
{
char
c;
while (cin.get(c)) cout << c;
}
Такая запись выглядит несимметрично, и у операции >> для вывода символов есть двойник под именем
put(), так что можно писать и так:
main()
{
char
c;
while (cin.get(c)) cout.put(c);
}
Функция с тремя параметрами istream::get() вводит в символьный вектор не менее n символов, начиная
с
адреса p. При всяком обращении к get() все символы, помещенные в буфер (если они были),
завершаются 0, поэтому если второй параметр равен n, то введено не более n-1 символов. Третий
параметр определяет символ, завершающий ввод. Типичное использование функции get() с тремя
параметрами сводится к чтению строки в
буфер заданного размера для ее дальнейшего разбора,
например так:
void f()
{
char
buf[100];
cin >> buf;
//
подозрительно
cin.get(buf,100,'\n');
//
надежно
//...
}
Операция cin>>buf подозрительна, поскольку строка из более чем 99 символов переполнит буфер. Если
обнаружен завершающий символ, то он остается в потоке первым символом подлежащим вводу. Это
позволяет проверять буфер на переполнение:
void f()
{
char
buf[100];
cin.get(buf,100,'\n'); //
надежно
char c;
if (cin.get(c) && c!='\n') {
// входная строка больше, чем ожидалось
}
//...
}
Естественно, существует версия get() для типа unsigned char.
В стандартном заголовочном файле
определены несколько функций, полезных для обработки
при вводе:
Бьерн Страуструп.
Язык программирования С++
263
int isalpha(char)
// 'a'..'z' 'A'..'Z'
int isupper(char)
// 'A'..'Z'
int islower(char)
// 'a'..'z'
int isdigit(char)
// '0'..'9'
int isxdigit(char)
// '0'..'9' 'a'..'f' 'A'..'F'
int isspace(char)
// ' ' '\
t' возвращает конец строки
// и перевод формата
int iscntrl(char)
// управляющий символ в диапазоне
// (ASCII 0..31 и 127)
int ispunct(char)
// знак пунктуации, отличен от
// приведенных выше
int isalnum(char)
// isalpha() | isdigit()
int isprint(char)
//
видимый: ascii ' '..'~'
int isgraph(char)
// isalpha() | isdigit() | ispunct()
int isascii(char c) { return 0<=c && c<=127; }
Все они, кроме isascii(), работают с помощью простого просмотра, используя символ как индекс в
таблице атрибутов символов. Поэтому вместо выражения типа
(('a'<=c && c<='z') || ('A'<=c && c<='Z')) // буква
которое не только утомительно писать, но оно может быть и ошибочным (на машине с кодировкой
EBCDIC оно задает не только буквы), лучше использовать вызов стандартной функции isalpha(),
который к тому же более эффективен. В качестве примера приведем функцию eatwhite(), которая читает
из потока обобщенные пробелы:
istream& eatwhite(istream& is)
{
char
c;
while (is.get(c)) {
if
(isspace(c)==0)
{
is.putback(c);
break;
}
}
return
is;
}
В
ней используется функция putback(), которая возвращает символ в поток, и он становится первым
подлежащим чтению.
Достарыңызбен бөлісу: