- •Конспект лекций Часть 2 Оглавление
- •Часть 2 1
- •8. Указатели
- •8.1. Указатели Понятие указателя
- •Работа с указателями
- •Арифметика указателей
- •Ошибки при работе с указателями
- •If (p1) // Если указатель не равен 0, то все в порядке
- •8.2. Указатели и массивы
- •9. Функции и структура программы
- •9.1. Создание и использование функций Процедурный подход к разработке программ
- •Int Максимум_строки (int Строка)
- •Int Минимум_строки (int Строка)
- •Int Максимум_столбца (int Столбец)
- •Int Минимум_столбца (int Столбец)
- •Определение функций в программе
- •Завершение работы функции (инструкция return)
- •If ( Ошибка )
- •Список параметров функций
- •Обращение к функциям в программе
- •Передача данных по значению
- •Передача данных с помощью указателей
- •Передача данных по ссылке
- •Перегружаемые функции
- •Параметры по умолчанию
- •Функции с переменным числом параметров
- •Рекурсивное использование функций
- •Передача функций в качестве параметров
- •Встраиваемые функции (inline - функции)
- •Прототипы функций
- •9.2. Структура программы. Глобальные и локальные данные (области видимости и время жизни) Структура программы
- •Глобальные и локальные данные
- •Классы памяти
- •Многофайловые проекты
- •10. Структуры, объединения, перечисления
- •10.1. Структуры Определение структур
- •Доступ к полям структур
- •Указатели на структуры
- •Структурные параметры функций
- •Битовые поля структур
- •10.2. Объединения Обычные объединения
- •Анонимные объединения
- •10.3. Перечисления
- •Void WriteColor (тип_Спектр c )
- •11. Организация работы с файлами
- •11.1. Потоки для работы с файлами Общие сведения
- •Пример работы с файлом
- •11.2. Работа с файлами Создание потока, открытие и закрытие файла
- •Запись и чтение данных в текстовых файлах
- •Запись и чтение данных в двоичном режиме
- •If ( !File ) // Проверили удалось ли открыть файл
- •Как обнаружить конец файла?
- •Прямой доступ при работе с файлами
- •If ( !File ) // Проверили удалось ли открыть файл
- •Статус потоков ввода-вывода
- •Некоторые другие функции управления потоками ввода-вывода
- •Примеры по работе с файлами
- •12. Работа с динамической памятью Распределение памяти при работе программы
- •Динамическое выделение и освобождение памяти в стиле c
- •Возможные ошибки при работе с динамической памятью
- •Динамические массивы
- •Одномерные однонаправленные списки
- •Одномерные двунаправленные списки
- •Многомерные списки
Запись и чтение данных в текстовых файлах
Запись и чтение данных в текстовых файлах ничем не отличается от способов ввода-вывода данных с помощью потоков cinиcout. Методы форматирования вывода и вводы данных остаются такими же (флаги форматирования, манипуляторы, функции потоков).
Необходимо помнить, что при использовании операции >> для чтения данных из текстовых файлов, процесс чтения останавливается при достижении пробельного символа (так же как и в потоках cinиcout). Поэтому для чтения строки текста, содержащей несколько слов, необходимо, как и раньше, использовать, например, функциюgetline ().
Запись и чтение данных в двоичном режиме
Для работы с файлом в двоичном режиме его необходимо открыть с флагом ios :: binary.
Чтение и запись двоичных данных в этом режиме можно осуществлять двумя способами:
по одному байту – функции файловых потоков get ()иput ();
блокам определенной длины - функции файловых потоков read ()иwrite ().
Один из вариантов прототипов функций get ()иput () (чаще всего используемый) выглядит так:
ifstream & get (char & ch);
ofstream & put (char ch);
Функция get () берет один символ из потока ввода, помещает его в символьный параметрchи возвращает ссылку на поток ввода. Когда достигается конец файла, значение ссылки на поток становится равным 0.
Функция put ()помещает символchв поток вывода и возвращает ссылку на поток вывода.
В следующей программе с помощью этих функций осуществляется запись в файл массива Аиз 5 целых чисел, чтение из файла этих данных в массивВи вывод массиваВна экран:
int main ()
{
setlocale (0, "");
// Запись массива А в_файл "E:\test.dat"
ofstream o_File; // Создали поток вывода для записи данных в файл
o_File.open ( "E:\\test.dat", ios::binary ); // Открыли файл
if (! o_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n" ;
return 0;
}
// Записываем данные из массива А в файл
int A[5] = {1, 2, 3, 4, 5};
char *ch = (char *) A; // ch –ссылка на массив А, как на массив символов (байт)
for (int I = 0; I < sizeof(A); ++ I)
o_File.put(ch[I]);
o_File.close(); // Закрываем файл
// Чтение данных из_файла "E:\test.dat" в массив В;
ifstream i_File; // Создали поток ввода для чтения данных из файла
i_File.open ( "E:\\test.dat", ios::binary ); // Открыли файл
if (! i_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n" ;
return 0;
}
// Читаем данные из файла в массив B
int B[5];
ch = (char *) B; // ch –ссылка на массив В, как на массив символов (байт)
int I = 0;
while (i_File)
i_File.get(ch[I++]);
// Предыдущий цикл можно записать короче, например, так:
// while (i_File.get(*ch++);
i_File.close(); // Закрываем файл
// Выводим массив В на экран
for (I = 0; I < 5; ++ I)
cout << B[I] << " ";
cout << endl;
system("pause");
return 0;
}
А вот как выглядит та же программа при использовании блочных функций чтения и записи (read ()иwrite ()) в двоичном режиме:
int main ()
{
setlocale (0, "");
// Запись массива А в_файл "E:\test.dat"
ofstream o_File; // Создали поток вывода для записи данных в файл
o_File.open ( "E:\\test.dat", ios::binary ); // Открыли файл
if ( ! o_File.is_open() ) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n" ;
return 0;
}
int A[5] = {1, 2, 3, 4, 5};
o_File.write ( (char *) A, sizeof (A) ); // Записываем данные из массива А в файл
o_File.close (); // Закрываем файл
// Чтение данных из_файла "E:\test.dat" в массив В;
ifstream i_File; // Создали поток ввода для чтения данных из файла
i_File.open ( "E:\\test.dat", ios::binary ); // Открыли файл
if ( ! i_File.is_open() ) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n" ;
return 0;
}
int B[5];
i_File.read ( (char *) B, sizeof (B) ); // Читаем данные из файла в массивB
i_File.close (); // Закрываем файл
// Выводим массив В на экран
for (int I = 0; I < 5; ++ I)
cout << B[I] << " ";
cout << endl;
system("pause");
return 0;
}
Функции read ()иwrite () имеют следующие прототипы:
ifstream & read (char * buf, streamsize n);
ofstream & write (const char * buf, streamsize n);
Первый параметр этих функций определяет адрес буфера (некоторого массива символов - байт) для чтения или записи данных в соответствующий файловый поток. Второй параметр задает количество символов – байт, которые необходимо взять из потока или записать в поток (тип данных streamsize – целый тип данных). Размер буфера должен соответствовать значению второго параметра.
Функция write () обеспечивает запись из буфера, адрес которого указан в первом параметре функции,nсимволов данных в поток вывода и возвращает ссылку на поток.
Функция read () обеспечивает запись из потока вводаnсимволов данных в память по адресу, указанному в первом параметреbuf. При достижении конца файла функция возвращает ссылку на поток, равную 0, а фактическое количество взятых из потока символов может быть меньше, чем значениеnвторого параметра (буфер заполнен не полностью). Фактическое количество считанных из потока ввода символов после выполнения последней операции чтения можно определить с помощью функции потока вводаgcount(). Следующий пример иллюстрирует использование функций блочного чтения и записи данных из произвольного файла.
void FileToScr (char * FileName)
{
fstream File ( FileName, ios::in | ios::binary );