В этом разделе, на примере разработки простых консольных приложений, мы поучимся выводить (и вводить) данные в файл с помощью функций библиотеки периода выполнения (C Runtime Library). Библиотека имеет довольно много функций для ввода-вывода как числовых, так и текстовых данных, но надо остановить свой выбор на каком-то их подмножестве и стараться не смешивать функции, прототипы которых описаны в разных файлах заголовков. Наиболее известны функции ввода-вывода, которые описаны в файле stdio.h. Они позволяют работать со стандартными потоками ввода-вывода:
¨ stdin — входной поток, который по умолчанию связан с клавиатурой
¨ stdout — выходной поток, связанный с экраном,
¨ stderr — поток, в который выводятся сообщения об ошибках или исключительных ситуациях (связан с экраном).
Эти потоки по сути являются указателями на специальный тип структур языка С, которые служат для управления вводом-выводом в файл и описаны как FILE *stdin, *stdout, *stderr;. Кроме того, вы можете создать свой поток типа FILE* и, связав его с определенным файлом, вводить или выводить свои данные.
Для начала создайте новый проект консольного приложения. Для этого выберите команду меню: File-New-Project, задайте в поле Location свою папку на диске, доступном для записи, выберите тип проекта Win32 Console Application, введите имя проекта, например, FileOp.
¨ Подключите к проекту новый файл типа C++ Source File (команда меню File-New-File), задайте ему имя, например, такое же, как и имя проекта).
¨ Перейдите в окно редактора (справа) и введите текст программы:
#include <stdio.h>
#include <stdlib.h>
void main()
{
printf ("\n\n Enter the file name: ");
char fn[_MAX_PATH]; // Здесь использована символическая константа _MAX_PATH (См. Help)
gets(fn); // Ввод строки с клавиатуры (точнее из потока stdin)
FILE *fp = fopen(fn,"wt"); // Пытаемся открыть файл и создать новую структуру типа FILE
if (!fp) // Если не получилось, то выводим сообщение и уходим
{
printf("\n Couldn't open %s\n\n",fn);
exit(-1); // Аварийное завершение консольного приложения
}
// Если файл открыт, то пытаемся вывести в него строку текста
char text[] = "\n\n The Miracle of technology";
if (fputs (text,fp) == EOF) // Если функция вернула EOF, то это - сбой
printf("\n\n Couldn't write to file\n\n");
else
{ // Если получилось, то сообщаем пользователю
fputs(text,stdout); // stdout - это стандартный выходной поток (связан с экраном)
puts("\n\n Wrote. Ok!\n"); // Вывод в тот же поток stdout (по умолчанию)
}
fclose(fp); // Закрываем файл (Должно войти в привычку).
}
Запустите на выполнение (Ctrl+F5). Проверьте наличие и содержимое вновь созданного текстового файла другими средствами, например, с помощью самой же студии разработчика. Обратите внимание на разнообразие функций вывода на экран (printf, puts, fputs). На экран можно вывести той же функцией (fputs), что и в файл, указав поток stdout. В заголовке stdio.h даны прототипы функций для работы с файлами. Там же определена специальная структура типа FILE, поля которой содержат системную информацию о файле, например: указатель на буфер обмена, размер буфера, флаги статуса файла и т. д. Пользователь может не знать подробности строения и использования системой этой структуры, но он должен описать переменную типа FILE* и использовать ее при вызове функций, оперирующих с файлами. Мы рекомендуем отыскать эту структуру в stdio.h и проанализировать смысл ее полей. При задании имен файлов удобно пользоваться символической константой _MAX_PATH, которая определена в stdlib.h, и служит для ограничения длины полного файлового пути.
Теперь для практики создадим две внешние (helper) функции для записи и чтения из файла и с их помощью выведем и снова введем информацию. При этом воспользуемся другими функциями (fwrite, fread) ввода-вывода, которые позволяют манипулировать массивами данных произвольного типа.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
// Наша функция записи в файл
bool WriteToFile (char* sText, char* sFileName)
{
printf ("\n\n Enter the file name: ");
gets(sFileName);
FILE *fp = fopen(sFileName,"wt");
if (!fp)
return false; // Возвращаем результат (неудача)
//==== sText - начало массива,
//==== sizeof(char) - размер одного элемента,
//==== strlen(sText) - количество элементов
int nItems = fwrite (sText, sizeof(char), strlen(sText), fp);
printf ("\n\n Wrote %d items\n",nItems);
fclose(fp);
return true; // Возвращаем результат (успех)
}
// Наша функция чтения из файла
bool ReadFromFile (char* sText, int size, char* sFileName)
{
FILE *fp;
if ((fp = fopen(sFileName,"rt"))==NULL)
return false;
int nItems = fread (sText, sizeof(char), size,fp);
printf ("\n\n %d items have been read\n\n",nItems);
fclose(fp);
return true;
}
void main()
{
// Этот текст мы запишем и снова прочтем
char poem[] =
"It's not learning, grace, nor gear,\n"
"Nor easy meat and drink,\n"
"But bitter pinch of pain and fear\n"
"That makes creation think.\n"
"\t - R. Kipling.\n\n";
char sFileName[_MAX_PATH];
//============= Пишем в файл ================//
bool bResult = WriteToFile(poem, sFileName);
if ( !bResult )
{
printf("\n Couldn't write to file %s\n\n",sFileName);
exit(-1);
}
//============ Предлагаем прочесть его =============//
printf ("\n\n File name: %s. Shall we read it? (Y/N)\n", sFileName);
if (toupper(getch())=='N') // Ждем реакцию (getch)
{
printf("\n Bye\n\n"); // В случае отказа уходим
exit(-1);
}
for (int i=0; poem[i]; i++) // Стираем текст перед тем, как прочесть
poem[i] = ' ';
//============ Читаем текст из файла =============//
bResult = ReadFromFile (poem, strlen(poem), sFileName);
if (!bResult)
printf("\n Couldn't read from file %s\n\n",sFileName);
else
puts(poem); // Выводим то, что прочли
}
При анализе кода попробуйте объяснить как работает механизм передачи формальных и фактических параметров при вызове функций WriteToFile и ReadFromFile.
Рассмотрим актуальную некогда задачу преобразования текстового файла из альтернативной кодировки (DOS-кодировки) в кодировку ANSI (Windows-кодировку). Альтернативную кодировку можно увидеть, если открыть Windows-утилиту Character Map и выбрать шрифт Terminal. Обратите внимание на местоположение русских букв в этой таблице. Они следуют с разрывом (между буквами 'п' и 'р'). Сравните эту кодировку с Windows-кодировкой, выбрав какой-либо другой шрифт, например, Times New Roman Cyr. Здесь символы следуют непрерывно и занимают самый низ таблицы. Теперь вам станет ясен алгоритм преобразования кодов:
¨ Если код символа находится в диапазоне между кодом буквы 'А' (128) и кодом буквы 'п' (175), то его надо сдвинуть на 64 единицы.
¨ Если код — в диапазоне между 'р' (224) и 'я' (240), то его надо сдвинуть на 16 единиц.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.