- •СОДЕРЖАНИЕ
- •ПРЕДИСЛОВИЕ
- •ГЛАВА 1. Введение в алгоритмы
- •1.1. Этапы решения задач на ЭВМ
- •1.2. Понятие алгоритма
- •1.3. Свойства алгоритмов
- •1.4. Сложность алгоритма
- •1.7. Пример простейшего линейного процесса
- •1.7. Пример циклического процесса
- •ГЛАВА 2. Базовые средства языка Си
- •2.1. Алфавит языка Си
- •2.2. Лексемы
- •2.3. Идентификаторы и ключевые слова
- •2.4. Комментарии
- •2.5. Простейшая программа
- •2.7. Декларация объектов
- •2.8. Данные целого типа (integer)
- •2.9. Данные символьного типа (char)
- •2.10. Данные вещественного типа (float, double)
- •ГЛАВА 3. Константы в программах
- •3.2. Константы вещественного типа
- •3.4. Строковые константы
- •ГЛАВА 4. Обзор операций
- •4.1. Операции, выражения
- •4.3. Операция присваивания
- •4.4. Сокращенная запись операции присваивания
- •4.7. Операции сравнения
- •4.8. Логические операции
- •4.10. Операция «,» (запятая)
- •ГЛАВА 5. Обзор базовых инструкций языка Си
- •5.2. Стандартные математические функции
- •5.3. Функции вывода данных на дисплей
- •5.4. Функции ввода информации
- •ГЛАВА 6. Составление разветвляющихся алгоритмов
- •6.1. Краткая характеристика операторов языка Си
- •ГЛАВА 7. Составление циклических алгоритмов
- •7.1. Понятие циклического кода
- •7.2. Оператор с предусловием while
- •7.4. Оператор цикла с предусловием и коррекцией for
- •ГЛАВА 8. Операторы и функции передачи управления
- •8.1. Оператор безусловного перехода goto
- •8.2. Операторы continue, break и return
- •8.3. Функции exit и abort
- •Советы по программированию
- •ГЛАВА 9. Указатели
- •9.1. Определение указателей
- •9.2. Операция sizeof
- •9.3. Инициализация указателей
- •9.4. Операции над указателями
- •ГЛАВА 10. Массивы
- •10.1. Понятие массива
- •10.2. Одномерные массивы
- •10.4. Строки как одномерные массивы данных типа char
- •10.5. Указатели на указатели
- •10.8. Работа с динамической памятью
- •10.9. Библиотечные функции
- •10.10. Пример создания одномерного динамического массива
- •ГЛАВА 11. Функции пользователя
- •11.1. Декларация функции
- •11.2. Вызов функции
- •11.3. Передача аргументов в функцию
- •11.4. Операция typedef
- •11.5. Указатели на функции
- •ГЛАВА 12. Классы памяти и область действия объектов
- •ЗАДАНИЕ 4. Обработка массивов
- •Первый уровень сложности
- •Второй уровень сложности
- •ЗАДАНИЕ 5. Функции пользователя
- •Первый уровень сложности
- •Второй уровень сложности
- •12.3. Статические и внешние переменные
- •12.4. Область действия переменных
- •Советы по программированию
- •13.1. Структуры
- •13.5. Вложенные структуры
- •13.6. Массивы структур
- •13.7. Размещение структурных переменных в памяти
- •13.8. Объединения
- •13.9. Перечисления
- •13.10. Битовые поля
- •ГЛАВА 14. Файлы в языке Си
- •14.1. Открытие файла
- •14.2. Закрытие файла
- •14.3. Запись-чтение информации
- •14.5. Дополнительные файловые функции
- •Советы по программированию
- •ЗАДАНИЕ 7. Создание и обработка файлов
- •Первый уровень сложности
- •Второй уровень сложности
- •ГЛАВА 15. Динамические структуры данных
- •15.1. Линейные списки
- •15.2.1. Алгоритм формирования стека
- •15.2.2. Алгоритм извлечения элемента из стека
- •15.2.3. Просмотр стека
- •15.2.4. Алгоритм освобождения памяти, занятой стеком
- •15.2.5. Алгоритм проверки правильности расстановки скобок
- •15.3.1. Формирование очереди
- •15.3.2. Алгоритм удаления первого элемента из очереди
- •15.4. Двунаправленный линейный список
- •15.4.1. Формирование первого элемента
- •15.4.3. Алгоритм просмотра списка
- •15.4.5. Алгоритм удаления элемента в списке по ключу
- •15.5. Нелинейные структуры данных
- •15.5.1. Бинарные деревья
- •15.5.2. Основные алгоритмы работы с бинарным деревом
- •15.5.4. Вставка нового элемента
- •15.6. Построение обратной польской записи
- •15.6.1. Алгоритм, использующий дерево
- •15.6.2. Алгоритм, использующий стек
- •15.6.3. Пример реализации
- •15.7. Понятие хеширования
- •15.7.2. Примеры хеш-функций
- •15.7.3. Схемы хеширования
- •15.7.4. Примеры реализации схем хеширования
- •Вариант 2. Двунаправленные списки
- •ГЛАВА 16. Переход к ООП
- •16.1. Потоковый ввод-вывод
- •16.3. Проблема ввода-вывода кириллицы в среде Visual C++
- •16.4. Операции new и delete
- •16.6. Шаблоны функций
- •Первый уровень сложности
- •Второй уровень сложности
- •6.1. Основные понятия
- •6.3. Примитивы GDI
- •6.5. Получение описателя контекста устройства
- •6.6. Основные инструменты графической подсистемы
- •6.7. Закрашивание пустот
- •6.8. Рисование линий и кривых
- •6.9. Пример изображения графика функции sin
- •6.10. Рисование замкнутых фигур
- •6.11. Функция Polygon и режим закрашивания многоугольника
- •6.13. Управление областями вывода и отсечением
- •ЗАДАНИЕ 11. Создание графических изображений
- •ЛИТЕРАТУРА
ГЛАВА 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) |
|
|
|
|
|
|
|
|
|
||||||
{ |
i, j, k; |
|
|
|
|
|
|
|
|
|
|
||||
int |
|
о |
|
|
// «end line» – переход на новую строку |
||||||||||
cout << “ Hello! ” << endl; |
|
||||||||||||||
|
|
|
и |
|
|
|
|
|
|
|
|
|
|
|
|
cout << “ Input |
i, j ”; |
|
|
|
|
|
|
|
|
|
|
||||
cin |
>> i >> j ; |
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
л |
|
|
|
|
|
|
|
|
|
|
|
|
|
k = i + j ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
||
coutб<< “ Sum i , j = “ << k << endl; |
|
|
|
|
|
|
|||||||||
и |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Б |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
В стандарте языка Си ANSI ввод-вывод данных осуществляется при помощи стандартных библиотечных функций. Управление выводом осуществляется при помощи использования форматов и управляющих символов.
Для форматирования и управления выводом данных в потоке введен механизм манипуляторов – специальных функций для модификации работы
168
потока, предназначенных для форматирования данных, как при выводе, так и в оперативной памяти.
Использование манипуляторов |
|
|
||
Манипуляторы |
– |
специальные |
функции, |
возвращающие |
модифицированные данные потока. В большинстве случаев их использование позволяет форматировать данные, как при выводе, так и в оперативной памяти.
Для их использования необходимо вместо файла 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 (заполнение пробел ми неиспользуемой части). |
|
Действует только для следующего за ним объекта. */ |
|
а |
|
к |
|
/* Манипулятор setwfill(kod) – усеанавливает заполнитель пробелов, заданный символом или его кодом (можно было указать 122 – код символа 'z'). На экране: zzzzzzz157. Дейс ву до изменения или отмены setwfill(0) .*/
cout << setw(10) << setfill(‘z’) << a << endl;
cout << oct << a <<етendl;
/* Манипулятор oct – вып лняет преобразование объекта в 8-ричную форму |
||
|
|
о |
представления. На экране: 235 */ |
||
|
и |
|
|
cout << hex << a << endl; |
|
|
л |
|
// hex – прео разует объект в 16-ричную форму. На экране: 9d |
||
|
бcout << dec << a << endl; |
|
// dec и– преобразует обратно в 10-тичную. На экране: 157 |
||
Б |
|
|
/* setprecision(n) – устанавливает n значащих цифр после запятой с учетом точки или без нее, в зависимости от системы программирования. На экране:
1.56или 1.556 */ return 0;
}
169
Флажки
Помимо манипуляторов для управления выводом данных используются специальные флажки, принадлежащие классу 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; |
|
|
||||
*****12.99 |
a2 *****15.00 |
|
|
|
|||
// На экране: a1 |
|
|
|
||||
и |
|
double pi = 3.14159; |
|
|
|
|
|
|
cout << “ Pi “ << setw(15) << setfill(‘_’) |
|
|
||||
|
|
|
|
||||
// С мвол заполнения ‘_’ – знак подчеркивания |
|
|
|||||
|
<< setiosflags(ios :: showpos | ios :: scientific) |
|
|
||||
|
<< setprecision(5) << pi << endl; |
|
|
|
|||
Б/* showpos – явно показать знак «+», scientific – вывод в форме с плавающей |
|||||||
десятичной точкой. На экране: Pi _ _ _ +3.14159e+00 |
|
*/ |
|||||
} |
|
|
|
|
|
|
|
В заключение отметим, что можно создавать свои собственные манипуляторы, которые будут выполнять запрограммированные действия.
170
16.3. Проблема ввода-вывода кириллицы в среде Visual C++
Работа в среде Visual C++ 6.0 (в режиме консольных приложений) сопряжена с определенными неудобствами. Например, попытка вывести фразу на русском языке, как стандартными функциями вывода, так и с помощью ввода-вывода потоками, терпит неудачу. Создадим в среде Visual C++ 6.0 консольное приложение и наберем следующий текст:
#include <iostream.h> |
|
|
|
int main() |
|
|
Р |
{ |
|
|
|
cout << "Welcome to C++ !" << endl; |
|
|
|
cout << "Добро пожаловать в C++ !" << endl; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
И |
||
В результате на экране получим нечто следующее: |
|
||
Welcome to C++ ! |
|
||
У |
|
||
─юсЕю яюцрыютрЄ№ т C++ ! |
|
||
Г |
|
|
|
Press any key to continue |
|
|
То есть вместо фразы на русском языкеаполучаетсяБбессмысленный набор символов. Это вызвано различными ст нд ртами кодировки символов кириллицы в операционных системах MS DOS и Windows.
Весь ввод-вывод в консольном о не идет в кодировке стандарта ASCII.
Данный стандарт является международным только в первой половине кодов, |
||||||||
|
|
|
|
|
к |
|
|
|
т.е. для кодов от 0 до 127, а вторая половина кодов от 128 до 255 |
||||||||
предназначена для национальныхешрифтов. Так, например, в бывшем СССР |
||||||||
помимо альтернативной к дировки ГОСТа (Alt), |
использовались – основная |
|||||||
кодировка ГОСТа (Mai), б лгарская кодировка |
(MIC), |
кодировка КОИ-8 |
||||||
|
|
|
|
т |
|
|
|
|
(KOI), у которых с мв лы кириллицы имеют разные коды. Сейчас в России – |
||||||||
альтернативная код |
ровка ASCII. |
|
|
|
|
|||
|
|
|
о |
|
|
|
|
|
Текст же в сходных файлах, набираемый в текстовом редакторе Visual |
||||||||
|
и |
|
|
|
|
|
||
C++, имеет кодировку в стандарте ANSI. Данный стандарт в первой половине |
||||||||
совпадает с альтернативной кодировкой ASCII, а во второй – отличается, так |
||||||||
и |
л |
|
|
|
|
|
|
|
|
Visual |
решили, |
что консольное приложение |
должно |
||||
как разра отчики |
||||||||
Б |
|
в среде MS DOS и оставили альтернативную кодировку |
||||||
имит роватьботура |
||||||||
ASCII. |
|
|
|
|
|
|
|
|
Для нормального |
вывода |
строки, содержащей |
буквы |
русского |
алфавита, надо использовать функцию CharToOem, предназначенную для преобразования символов с кодировкой ANSI в кодировку ASCII. Аналогично, если в программе есть консольный ввод текста и этот текст в дальнейшем надо сохранять в документах (файлах) с кодировкой ANSI, то перед сохранением нужно воспользоваться функцией обратного преобразования – OemToChar. Эти функции декларированы в заголовочном файле windows.h.
171
С учетом сказанного выше можно предложить следующую программу корректного вывода информации на русском языке:
#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 нельзя использовать в цепочке операций << более одного раза, так как для различных компиляторов и режимов оптимизации может быть получен неверный результат.
172