Специальные функции ввода текстовых данных
Специальные функции ввода символьных данных getch() и getche() упрощают их набор (не приходится дополнительно нажимать клавишу Enter) и предоставляют дополнительные возможности. Ниже приводится программа и результат ее работы после нажатия на цифровую клавишу 5.
#include <stdio.h>
#include <conio.h>
void main()
{ char ch[4]={'1','2','3'};
ch[1]=getch();
printf("ch[0]=%c ch[1]=%c ch[2]=%c",ch[0],ch[1],ch[2]);
getch();
return;
}
//=== Результат работы ===
ch[0]=1 ch[2]=5 ch[3]=3
Функция getch (от get character – дай символ) организует ввод кода символа без эхо-сигнала, т.е. без отображения на экране знака, соответствующего нажатой клавише. Такая возможность может оказаться полезной при вводе секретных данных (пароль) или в ситуации, когда отображение символа нажатой клавиши может повредить текущее содержимое экрана. Очень часто эту функцию используют в качестве задержки работы программы до нажатия какой-либо клавиши.
Функция getche обеспечивает ввод символа, соответствующего нажатой клавише с выдачей эхо-сигнала.
Обе функции обращаются к буферу клавиатуры. Если к этому моменту буфер пуст, то происходит ожидание нажатия клавиши. Считанный символ из буфера клавиатуры выталкивается. Однако клавиши на клавиатуре разные. Большая их часть связана с отображаемыми символами – буквами, цифрами, знаками препинания и т.п. После их нажатия обращение к функциям getch/getche приводит к считыванию соответствующего кода
ASCII. В частности, к "отображаемым" клавишам относятся клавиши Esc (код 27), Enter (код 13), комбинация Ctrl+Z (код 26 – признак конца файла). Но на клавиатуре присутствует ряд клавиш, с которыми ассоциируются управляющие символы, не представленные в таблице ASCII. К ним, в частности, относятся функциональные клавиши F1, F2, …, стрелки управления курсором, клавиши Insert и Delete и др. От их нажатия в буфер клавиатуры поступает двухбайтовый код, содержащий в старшем байте 0, а в младшем байте так называемый scan-код (некий порядковый код, приписанный каждой клавише). В этом случае первое обращение к функциям getch/getche приводит к считыванию нулевого кода, а повторное обращение возвращает scan-код ранее нажатой клавиши. Таким образом, для анализа кода нажатой управляющей клавиши к функциям getch/getche приходится обращаться дважды (предварительно следует убедиться в том, что первое обращение возвратило 0).
Функция gets (от get string – дай строку) позволяет ввести в символьный массив текстовое значение, содержащее пробелы:
#include <stdio.h>
#include <conio.h>
void main()
{ char str[80];
gets(str);
printf("\nstr=%s",str);
getch();
}
При потоковом вводе со стандартного устройства stdin можно запросить заданное количество k символов, среди которых может встретиться и пробел:
cin.getline(str,k);
При этом можно ввести не более чем k-1 символ, т.к. нужно помнить о резервном байте для признака окончания строки. Если строка, набираемая пользователем, содержит более чем k-1 символ, то продолжение строки будет проигнорировано. И даже последующий оператор ввода не сможет им воспользоваться. Если строка ввода содержит меньше, чем k-1 символ, то она будет введена целиком. Более того, с помощью еще одного параметра, – символа завершения операции, можно досрочно прекратить ввод:
cin.getline(str,k,'Q');
Если в строке ввода будет досрочно обнаружен символ 'Q', то он уже не вводится.
Следует упомянуть еще одну функцию форматного ввода cscanf, ориентированную на работу с конкретным устройством – клавиатурой. Обращаются к ней точно так же как и к функции scanf, но они не дублируют друг друга. И вот почему. Дело в том, что стандартные устройства ввода (stdin) и вывода (stdout) могут быть подменены другими носителями информации (например, файлами или принтером). А ввод с клавиатуры и вывод на экран дисплея, образующих в совокупности консоль (пульт) оператора, переназначить нельзя.
Вывод текстовых данных
При выводе текстовых данных особые проблемы возникают только в том случае, когда сообщения, содержащие русские буквы, готовятся в среде Windows (кодовая страница 1251), а выводятся консольным приложением в 866-й кодовой странице. В этом случае можно написать сравнительно несложную функцию конвертирования текстов из одной кодировки в другую. В кодовой странице 1251 буквы русского алфавита кодируются подряд, начиная с кода 192 (большая буква 'А') до кода 255 (малая буква 'я'). Буквы 'Ё' и 'ё' имеют коды 164 и 184 соответственно. Поэтому при перекодировке необходимо:
· коды букв, принадлежащие интервалу [192, 239] уменьшить на 64, чтобы вогнать их в интервал [128, 174];
· коды букв, принадлежащие интервалу [240, 255] уменьшить на 16, чтобы вогнать их в интервал [224, 239];
· коды букв Ё и ё заменить на 240 и 241 соответственно.
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
#include <string.h>
char *to_866(unsigned char *s)
{ static unsigned char str[80];
int j=0;
while (s[j]!='\0')
{ str[j]=s[j];
if(s[j]>=192 && s[j]<=239) str[j]-=64;
if(s[j]>=240 && s[j]<=255) str[j]-=16;
if(s[j]==164) str[j]=240;
if(s[j]==184) str[j]=241;
j++;
}
str[j]='\0';
return str;
}
void main()
{ char s[]="Привет;
cout << s << endl;
cout <<to_866(s) << endl;
getch();
}
//=== Результат работы ===
В первой строке вывод реализован без перекодировки, а во второй – с перекодировкой.
Форматный вывод
Для форматного вывода символьных значений в функции printf используется форматный указатель %c, а для вывода строк – форматный указатель %s. При создании консольных приложений Windows можно воспользоваться программой перекодировки, аналогичной функции to_866.
#include <stdio.h>
#include <conio.h>
void main()
{
char ch1='F';
unsigned char ch2='5';
char ch3[]="ABCD";
printf("%c %c %s",ch1,ch2,ch3);
getch();
}
//=== Результат работы ===
F 5 ABCD
Потоковый вывод
В потоковом выводе единственная проблема может возникнуть в связи с перекодировкой русских сообщений в консольном приложении Windows.
#include <iostream.h>
#include <conio.h>
void main()
{
char ch1='F';
unsigned char ch2='5';
char ch3[]="ABCD";
cout<<ch1<<' '<<ch2<<' '<<ch3;
getch();
}
//=== Результат работы ===
F 5 ABCD