- •Приложение г Лекция 1. Элементы Языка си Используемые символы
- •Константы
- •Идентификаторы
- •Ключевые слова
- •Использование комментариев в тексте программы
- •Лекция 2. Типы данных и их объявление
- •Категории типов данных
- •Целый тип данных
- •Данные вещественного типа
- •Указатели
- •Операции разадресации и адреса
- •Переменные перечислимого типа
- •Лекция 3. Выражения и присваивания Операнды и операции
- •Преобразования при вычислении выражений
- •Операции отрицания и дополнения
- •Операция sizeof
- •Мультипликативные операции
- •Аддитивные операции
- •Операции сдвига
- •Поразрядные операции
- •Логические операции
- •Операция последовательного вычисления
- •Условная (тернарная) операция
- •Операции увеличения и уменьшения
- •Простое присваивание
- •Составное присваивание
- •Приоритеты операций и порядок вычислений
- •Побочные эффекты
- •Преобразование типов
- •Лекция 3. Операторы
- •Оператор выражение
- •Пустой оператор
- •Составной оператор
- •Оператор if
- •Оператор switch
- •Оператор break
- •Оператор while
- •Оператор do while
- •Оператор for
- •Сумма чисел от 1 до 100
- •Микрожизнь
- •Оператор continue
- •Оператор return
- •Оператор goto
- •Лекция 4. Массивы
- •Поиск минимума, сортировка
- •Ввод-вывод, обнуление
- •Двумерный массив
- •Лекция 5. Структуры
- •Объединения (смеси)
- •Поля битов
- •Переменные с изменяемой структурой
- •Определение объектов и типов
- •Лекция 6. Инициализация данных
- •Определение и вызов функций
- •Ссылки как псевдонимы переменных
- •Ссылки в качестве параметров функции
- •Ссылка в качестве возвращаемого значения
- •Передача массивов
- •Прототип
- •Указатели на функцию
- •Рекурсия
- •Предварительная инициализация параметров функции
- •Функции с переменным числом параметров
- •Передача параметров функции main
- •Исходные файлы и объявление переменных
- •Объявления функций
- •Время жизни и область видимости программных объектов
- •Лекция 7. Инициализация глобальных и локальных переменных
- •Методы доступа к элементам массивов
- •Указатели на многомерные массивы
- •Операции с указателями
- •Массивы указателей
- •Лекция 8. Динамические объекты
- •1. Выделение памяти в соответствие с типом указателя
- •2. Выделение памяти под нетипизированный указатель
- •Лекция 9. Динамическое создание и уничтожение массивов
- •Директивы Препроцессора
- •Директива #include
- •Директива #define
- •Директива #undef
- •Лекция 10. Условные директивы препроцессора
- •Линейный односвязный список
- •Лекция 11. Объектно-ориентированный подход к программированию
- •Ссылки на Себя
- •Инициализация
- •Копирующий конструктор
- •Очистка
- •Законченный Класс
- •Доступ к членам
- •Статические Члены
- •Лекция 12. Наследование
- •Перегрузка Операций
- •Операции Преобразования
- •Стандартный ввод/вывод
- •Форматируемый вывод
- •Манипуляторы
- •Ввод-вывод двоичных данных
- •Ввод/вывод с диска
- •Ввод/вывод для типов данных, определенных пользователем
- •Шаблоны функций
- •Шаблоны классов
- •Лекция 14. Библиотека stl
- •Итераторы
- •Алгоритмы
- •Контейнеры
- •Функциональные объекты
- •Пример. Работа с контейнером vector
- •Пример 2. Алгоритмы и функциональные объекты
- •Лекция 15. Обработка исключительных ситуаций
- •Лекция 16. Rtti и приведение типов
- •Операция typeid
Ввод-вывод двоичных данных
Для ввода-вывода двоичных данных используются функции (методы классов ostream и istream) put, write и get, которые определены следующим образом:
ostream& ostream::put(char ch);
//посылает ch в ostream
ostream& ostream::write(const char* buff, int n);
//посылает n символов из buff в ostream;
Put и write позволяют выводить неформатированные двоичные данные в объект ostream. Put выводит один символ, а write может послать любое количество символов из указанного буфера. Write полезна, когда нужно вывести необработанные данные, которые могут включать нули. (Запись двоичных данных требует, чтобы файл был открыт в двоичном режиме.)
Обычное извлечение строки не будет работать до тех пор, пока строка не будет завершена нулем.
Входная версия put называется get:
char ch;
cin.get(ch); //захватывает следующий символ из
//cin независимо от того пробел это или нет
Другая версия get позволяет захватывать любое количество необработанных, двоичных символов из istream до заданного максимума и помещать их в заданный буфер (так же, как и в случае с write, файлы должны быть открыты в двоичном режиме):
istream& istream::get(char *buff, int max, int term='\n');
//читает символы до максимального количества из istream, а
//затем помещает их в buff. Прекращает чтение, если
//прочитан
//символ, указанный в term.
Можно установить term равным определенному конечному символу (по умолчанию — это символ новой строки), в котором get будет прекращать работу, если он будет достигнут прежде, чем max символов будет передано в buff.
Ввод/вывод с диска
Библиотека iostream включает много классов, порожденных из streambuf, ostream и istream, предоставляя, таким образом, широкий выбор методов ввода/вывода файлов. Класс filebuf например, поддерживает ввод/вывод через дескрипторы файлов с помощью функций элементов для открытия, закрытия и поиска.
Наиболее часто используемыми классами являются ifstream (порожденный из istream), ofstream (порожденный из ostream) и fstream (порожденный из iostream). Все они поддерживают форматированный файл ввода/вывода, используя объекты filebuf. Ниже приведен простой пример, который копирует существующий дисковый файл в другой заданный файл:
/* DCOPY исходный файл / файл назначения *
* копирует существующий исходный файл в файл назначения *
* Если последний существует, то он перезаписывается; *
* если не существует, DCOPY создаст его, если это возможно *
*/
#include <iostream.h>
#include <process.h> // для exit()
#include <fstream.h> // для ifstream, ofstream
int main(int argc, char* argv[])
{
char ch;
if (argc != 3) // проверка числа аргументов
{
cerr << "USAGE: dcopy file1 file2\n";
exit(-1);
}
ifstream source; // объявить входной и выходной потоки
ofstream dest;
source.open(argv[1],ios::nocreate); // должен быть исходный файл
if (!source)
{
cerr << "Cannot open source file " << argv[1] << " for input\n";
exit(-1);
}
dest.open(argv[2]); // файл назначения будет создан, если
// не он найден или создан/перезаписан, если найден
if (!dest)
{
cerr << "Cannot open destination file " << argv[2] << " for output\n";
exit(-1);
}
while (dest && source.get(ch))
dest.put(ch);
cout << "DCOPY completed\n";
source.close(); // закрыть оба потока
dest.close();
}
Типичный вызов этой программы в командной строке выглядит следующим образом:
dcopy letter.spr letter.bak
Пример 2. Разработать программу для ввода/вывода с диска массива структур.
#include <iostream.h>
#include <fstream.h>
int main(int argc, char* argv[])
{
struct emp
{
char* name;
int dept;
};
emp e[2];
e[0].name="aaaa";
e[0].dept=1;
e[1].name="bbbbbbb";
e[1].dept=2;
ifstream source;
ofstream dest;
char filename[20]="s.dat";
dest.open(filename);
for(int i=0;i<2;i++)
dest<<e[i].name<<" "<<e[i].dept<<endl;
dest.close();
source.open(filename,ios::nocreate); // файл должен быть создан
for(int i=0;i<2;i++)
{
source>>e[i].name>>e[i].dept;
cout<<e[i].name<<" "<<e[i].dept<<endl;
}
source.close();
cin.get();
return 0;
}
При этом файл s.datсодержит следующие данные:
aaaa 1
bbbbbbb 2
Если поле nameможет содержать пробелы, то такой способ ввода/вывода непригоден. Нужно использовать разделитель полей, отличный от пробела, например,@.
for(int i=0;i<2;i++)
dest<<e[i].name<<"@"<<e[i].dept<<endl;
Теперь чтение данных будет выглядеть следующим образом:
char buf[22];
for(int i=0;i<2;i++)
{
source.get(e[i].name, 100, '@');
source.get(); //отбросить @
source.get(buf, 100, '\n');
source.get(); //отбросить \n
e[i].dept=atoi(buf);
cout<<e[i].name<<" "<<e[i].dept<<endl;
}