Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метода по ОАиП.doc
Скачиваний:
12
Добавлен:
11.05.2015
Размер:
3.21 Mб
Скачать

Глава 16. Переход к ооп

При переходе от языка Си к языку С++ в стандарт ANSIбыли введены дополнительные механизмы, которые позволили в конечном итоге создать среду для разработки программ в объектно-ориентированном стиле.

Рассмотрим некоторые из них.

16.1. Потоковый ввод-вывод

Поток – это абстрактное понятие, которое относится к любому переносу данных от источника к приемнику. Потоки С++ обеспечивают надежную работу как со стандартными (stdin,stdout), так и с определенными пользователями типами данных. Поток определяется как последовательность байт, не зависящая от конкретного устройства.

Для ввода-вывода в языке С++ используются два объекта класса iostream:cin(классistream),cout(классostream) и две переопределенные операции побитового сдвига. Для их работы необходимо подключить заголовочный файлiostream.h.

Формат записи операций помещения в поток<< (вывод на экран) иизвлечения из потока>> (ввод с клавиатуры) следующий:

cout<<ID переменной;

cin>>ID переменной;

Стандартный поток вывода coutпо умолчанию связан со стандартным устройством выводаstdout(дисплей монитора), а вводаcin– со стандартным устройством вводаstdin, т.е. клавиатурой. Приведем пример:

#include<iostream.h>

void main (void)

{

int i, j, k;

cout << “ Hello! ” << endl; // «end line» – переход на новую строку

cout << “ Input i, j ”;

cin >> i >> j ;

k = i + j ;

cout << “ Sum i , j = “ << k << endl;

}

16.2. Управление выводом

В стандарте языка Си ANSIввод-вывод данных осуществляется при помощи стандартных библиотечных функций. Управление выводом осуществляется при помощи использования форматов и управляющих символов.

Для форматирования и управления выводом данных в потоке введен механизм манипуляторов– специальных функций для модификации работы потока, предназначенных для форматирования данных, как при выводе, так и в оперативной памяти.

Использование манипуляторов

Манипуляторы – специальные функции, возвращающие модифицированные данные потока. В большинстве случаев их использование позволяет форматировать данные, как при выводе, так и в оперативной памяти.

Для их использования необходимо вместо файла iostream.hподключить заголовочный файлiomanip.h(манипуляторы для вывода потоками).

Рассмотрим работу некоторых манипуляторов на конкретном примере.

#include<iomanip.h>

main()

{

int a = 157;

double b = 1.55555;

cout << setw(10) << a << endl;

/* Манипулятор setw(n) – устанавливает ширину поля, т.е.nпозиций, для вывода объекта. На экране объектабудет выводиться с 8-й позиции, первые 7 позиций – пустые: 157 (заполнение пробелами неиспользуемой части). Действует только для следующего за ним объекта. */

cout<<setw(10) <<setfill(‘z’) <<a<<endl;

/* Манипулятор setwfill(kod) – устанавливает заполнитель пробелов, задан­ный символом или его кодом (можно было указать 122 – код символа 'z'). На экране:zzzzzzz157. Действует до изменения или отменыsetwfill(0) .*/

cout<<oct<<a<<endl;

/* Манипулятор oct– выполняет преобразование объекта в 8-ричную форму представления. На экране: 235 */

cout<<hex<<a<<endl;

// hex– преобразует объект в 16-ричную форму. На экране: 9d

cout << dec << a << endl;

// dec– преобразует обратно в 10-тичную. На экране: 157

cout<<b<<endl; // На экране: 1.55555

cout<<setprecision(3) <<b<<endl;

/* setprecision(n) – устанавливаетnзначащих цифр после запятой с учетом точки или без нее, в зависимости от системы программирования. На экране:

1.56 или 1.556 */

return0;

}

Флажки

Помимо манипуляторов для управления выводом данных используются специальные флажки, принадлежащие классу ios, которые также позволяют формировать потоки вывода.

Установить флажок позволяет функция setiosflags(ios::flag);

Снять флажок позволяет функция resetiosflags(ios::flag);

Причем можно установить сразу несколько флажков, используя для этого побитовую операцию «|» (поразрядное ИЛИ) для их объединения в одну группу.

Следующий пример показывает приемы работы с некоторыми флажками механизма вывода потоками.

#include<iostream.h>

#include<iomanip.h>

#include<conio.h>

void main(void) {

int a = 157;

cout<<setiosflags(ios :: showbase)<<a<<“ “<<oct<<a<< “ “

<<hex<<a<<endl;

/* showbase– показать, в какой системе счисления выводится число. На экране: 157 0235 0х9d */

double a1 = 12.99, a2 = 15;

cout << setiosflags(ios :: showpoint | ios :: fixed)

/* showpoint– печатать десятичную точку,fixed– выводить в форме с фиксированной десятичной точкой */

<< setprecision(2) << setfill(‘*’) << setiosflags(ios :: right)

// right– выравнивать вывод по правому краю(по левому – left)

<< “ a1 “ << setw(10) << a1

<< “ a2 “ << setw(10) << a2 << endl;

// На экране: a1 *****12.99 a2 *****15.00

double pi = 3.14159;

cout << “ Pi “ << setw(15) << setfill(‘_’)

// Символ заполнения ‘_’ – знак подчеркивания

<< setiosflags(ios :: showpos | ios :: scientific)

<< setprecision(5) <<pi<<endl;

/* showpos– явно показать знак «+»,scientific – вывод в форме с плавающей десятичной точкой. На экране:Pi_ _ _ +3.14159e+00 */

}

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

16.3. Проблема ввода-вывода кириллицы в среде Visual C++

Работа в среде VisualC++ 6.0 (в режиме консольных приложений) сопряжена с определенными неудобствами. Например, попытка вывести фразу на русском языке, как стандартными функциями вывода, так и с помощью ввода-вывода потоками, терпит неудачу. Создадим в средеVisualC++ 6.0 консольное приложение и наберем следующий текст:

#include <iostream.h>

int main()

{

cout << "Welcome to C++ !" << endl;

cout<< "Добро пожаловать вC++ !" <<endl;

return0;

}

В результате на экране получим нечто следующее:

Welcome to C++ !

юсЕю яюцрыютрЄт C++ !

Press any key to continue

То есть вместо фразы на русском языке получается бессмысленный набор символов. Это вызвано различными стандартами кодировки символов кириллицы в операционных системах MS DOSиWindows.

Весь ввод-вывод в консольном окне идет в кодировке стандарта ASCII. Данный стандарт является международным только в первой половине кодов, т.е. для кодов от 0 до 127, а вторая половина кодов от 128 до 255 предназначена для национальных шрифтов. Так, например, в бывшем СССР помимо альтернативной кодировки ГОСТа (Alt), использовались – основная кодировка ГОСТа (Mai), болгарская кодировка (MIC), кодировка КОИ-8 (KOI), у которых символы кириллицы имеют разные коды. Сейчас в России – альтернативная кодировкаASCII.

Текст же в исходных файлах, набираемый в текстовом редакторе VisualC++, имеет кодировку в стандартеANSI. Данный стандарт в первой половине совпадает с альтернативной кодировкойASCII, а во второй – отличается, так как разработчикиVisualрешили, что консольное приложение должно имитировать работу в средеMS DOSи оставили альтернативную кодировкуASCII.

Для нормального вывода строки, содержащей буквы русского алфавита, надо использовать функцию CharToOem, предназначенную для преобразования символов с кодировкойANSIв кодировкуASCII. Аналогично, если в программе есть консольный ввод текста и этот текст в дальнейшем надо сохранять в документах (файлах) с кодировкойANSI, то перед сохранением нужно воспользоваться функцией обратного преобразования –OemToChar. Эти функции декларированы в заголовочном файлеwindows.h.

С учетом сказанного выше можно предложить следующую программу корректного вывода информации на русском языке:

#include <iostream.h>

#include <windows.h>

char* Rus(const char* text);

char bufRus[255];

int main()

{

char s[] = "Минск!", ss[100];

cout << Rus("Город ") << Rus(s) <<endl;

cout << Rus("Введи строку:");

cin >> ss;

cout << Rus(" Строка: ") << ss << endl;

return 0;

}

char* Rus (const char* text)

{

CharToOem(text, bufRus);

return bufRus;

}

Результат программы может быть следующим:

Город Минск!

Введи строку: Москва!

Строка: Москва!

Таким образом, для решения проблемы с русским языком в консольном выводе Visual C++ 6.0 создана небольшая функция Rus, которая обращается к функции CharToOem, передает ей для преобразования полученный через свой параметр текст на русском языке и возвращает указатель на преобразованную строку. В качестве временного хранилища используется глобальный символьный массив bufRus. Использовать функцию просто: везде вместо строковых объектов (строковых констант и переменных) в программах нужно писать Rus(строковый объект).

Непосредственное использование функции CharToOem, например, в стандартных функциях вывода данных недопустимо, так как возвращает результат типа BOOL, а результат преобразования размещает по адресу своего второго аргумента. Поэтому и была создана эта небольшая пользовательская функция, которая имеет единственное ограничение: функцию Rus нельзя использовать в цепочке операций << более одного раза, так как для различных компиляторов и режимов оптимизации может быть получен неверный результат.