Работа с файлами в С++
Федеральное государственное бюджетное образовательное учреждение высшего образования
«Российская академия народного хозяйства и государственной службы
при Президенте Российской Федерации»
Поволжский институт управления им. П.А. Столыпина
Факультет государственного и муниципального управления
Направление подготовки 09.03.03 «Прикладная информатика»
Кафедра прикладной информатики и информационных технологий в управлении
КУРСОВАЯ РАБОТА
по дисциплине: «Программирование»
на тему:
«Работа с файлами в С++»
Автор работы:
студентка 1 курса 109 группы
очной формы обучения
Корниенко Юлия Романовна
Руководитель работы:
к.ф.- м.н., доцент
Успенский Кирилл Евгеньевич
Оценка______________________
Подпись_____________________
«____»_________2016 г.
Саратов 2016
Содержание
С.
Введение
В настоящее время, никто и ничто не обходится без использования IT-технологий, которые основываются на различных языках программирования. Они применяются во всех сферах жизнедеятельности: в медицине, образовании, проектировании зданий и сооружений, и т.д. Для каждой из них разрабатываются соответствующие программы. И поэтому, знание языков программирования является актуальным на сегодняшний день.
Язык программирования функционирует для двух целей:
- он предоставляет программисту аппарат для воплощения в реальность определенных действий;
- он формирует концепции, используемые программистом, когда тот размышляет о своих будущих действиях.
Для достижения первой цели достаточно хорошо подходит язык, который считают очень «близким к машине», и благодаря ему, специалисту нетрудно управлять всеми техническими аспектами. Именно для этого изначально задумывался язык C. А для выполнения достижения второй цели подходит язык, считаемый «близким к решаемой задаче», который поможет выразить решение более конкретно, то есть прямо и коротко. Приобщенные к C для формирования C++ средства и функции изначально были придуманы именно для этого.
Довольно близка связь между языками, на котором мы думаем и на котором мы решаем определенные задачи в своем воображении. Поэтому опасно стремиться только лишь исключить ошибки и погрешности программиста, ограничивая функциональность языка. Именно для этого в случае с повседневным использованием языка рекомендуется знать хотя бы два языка. Благодаря языку программист обладает набором инструментов, но на них просто не обращают внимания, если не соответствуют поставленной задаче. И грамотное проектирование не гарантируется только лишь за счет языковых средств.
В настоящее время язык C++ преобладает над другими языками программирования, так как он самый используемый для создания программных продуктов. И это выражает актуальность данной курсовой работы.
В данной курсовой работе на достижение поставлена следующая цель – раскрытие истории происхождения языка программирования C++ и работы с файлами в нем.
Для достижения цели были определены следующие задачи:
1. Сопоставить язык
2. Раскрыть эффективность и структуру языка программирования С++.
3. Привести пример работы с текстовыми файлами.
4. Привести пример работы с бинарными файлами.
Объектом исследования данной курсовой работы выступает язык программирования C++.
Предметом исследования являются технологические возможности данного языка, а в частности, работа с текстовыми и бинарными файлами в C++.
Глава 1. Возникновение и эволюция языка в С++
1.1. Возникновение и развитие языка С++
Бьерн Страуструп является разработчиком языка программирования C++, а также создателем первого транслятора. Ещё он является сотрудником AT&T Bell Laboratories (научно-исследовательский вычислительный центр) в Мюррей Хилл (Нью-Джерси, США). Бьерн Страуструп – магистр математики и вычислительной техники. Это звание он получил в университете города Аарус (Дания). А докторскую степень он получил в кембриджском университете (Англия). Он специализируется в сфере операционных систем, распределенных систем, программирования и моделирования. Совместно с М.А. Эллис Бьерн Страуструп – автор книги «Руководство по C++ с примечаниями».
Язык C существует как подмножество C++, хотя именно C++ обязан языку C, потому что C++ создан на основе C. Все средства низкого уровня, предопределенные для решения важных задач и проблем системного программирования, характерные C, сохранены. А предшественником C был язык BCPL, из которого было взято достаточно много, и, так же, как и в BCPL, в C++ нет блока VALOF. А концепция классов, производные классы, виртуальные функции были черпаны из такого языка, как SIMULA-67. Например, из него в C++ был взят оператор inspect, так как при работе в C++ хотелось видеть модульность, применяя виртуальные функции. Возможность совершать такие функции, как перезагрузка операций, свободное размещение комментариев везде, где может быть оператор, в C++ походят на язык Алгол-681.
Ранее существовала версия «С с классами», которой пользовались с 1980года. Возникла данная версия при появлении потребности создания программ моделирования, которые управляли прерываниями. И если не брать во внимание эффективность, то для создания подобных программ подходит язык SIMULA-67. «C с классами» применялся для более масштабных задач моделирования.
Строгой проверке подверглись тогда возможности написания на нем программ, для которых критичны ресурсы времени и памяти. В этом языке недоставало перегрузки операций, ссылок, виртуальных функций и многих других возможностей. Впервые С++ вышел за пределы исследовательской группы, в которой работал автор, в июле 1983 г., однако тогда многие возможности С++ еще не были разработаны.
Название С++ (си плюс плюс), было придумано Риком Маскитти летом 1983 г. Это название отражает эволюционный характер изменений языка С. Обозначение ++ относится к операции наращивания С. Чуть более короткое имя С+ является синтаксической ошибкой. Кроме того, оно уже было использовано как название совсем другого языка. Язык не получил названия В, поскольку он является расширением С, и в нем не делается попыток решить какие-либо проблемы за счет отказа от возможностей С.
Изначально С++ был задуман для того, чтобы автору и его друзьям не надо было программировать на ассемблере, С или других современных языках высокого уровня. Основное его предназначение – упростить и сделать более приятным процесс программирования для отдельного программиста. До недавнего времени не было плана разработки С++ на бумаге. Проектирование, реализация и документирование шли параллельно. Никогда не существовало «проекта С++» или «Комитета по разработке С++». Поэтому язык развивался и продолжает развиваться так, чтобы преодолеть все проблемы, с которыми столкнулись пользователи. Толчками к развитию служат также и обсуждения автором всех проблем с его друзьями и коллегами.
С момента выхода в свет первого издания этой книги язык С++ подвергся существенным изменениям и уточнениям. В основном это касается разрешения неоднозначности при перегрузке, связывании и управлении памятью. Вместе с тем, были внесены незначительные изменения с целью увеличить совместимость с языком С, были также введены некоторые обобщения и существенные расширения, как: множественное наследование, функции-члены со спецификациями static и const, защищенные члены (protected), шаблоны типа и обработка особых ситуаций. Все эти расширения и доработки были нацелены на то, чтобы С++ стал языком, на котором можно создавать и использовать библиотеки.
Другие расширения, введенные за период между 1985 и 1991 гг. (такие как множественное наследование, статические функции-члены и чистые виртуальные функции), скорее появились в результате обобщения опыта программирования на С++, чем были почерпнуты из других языков.
Сделанные за эти шесть лет расширения языка прежде всего были направлены на повышение выразительности С++ как языка абстракции данных и объектно-ориентированного программирования вообще и как средства для создания высококачественных библиотек с пользовательскими типами данных, в частности.
Примерно в 1987 г. стало очевидно, что работа по стандартизации С++ неизбежна и что следует незамедлительно приступить к созданию основы для нее.
Фирма АТ&Т Bell Laboratories внесла основной вклад в эту работу. Около ста представителей из порядка 20 организаций изучали и комментировали то, что стало современной версией справочного руководства и исходными материалами для АNSI по стандартизации С++.
Наконец, по инициативе фирмы Немец-РайсКого в декабре 1989 г. в составе АNSI был образован комитет Х3J16. Ожидается, что работы по стандартизации С++ в АNSI (американский стандарт) станут составной частью работ по стандартизации силами 180 (Международной организации по стандартизации). С++ развивался одновременно с развитием некоторых фундаментальных классов.2
Таким образом, язык программированияC++имеет достаточно длинную историю возникновения и разработки. При создании данного языка разработчики в основу брали различные составляющие из других языков программирования, таких как SIMULA-67, Алгол-68 и мн. др. И сейчас он является актуальным, так как большинство программистов в настоящее время работает именно в C++.
1.2. Эффективность и структура
В С++ особое внимание уделяется структурированию программы. Это вызвано увеличением размеров программ со времени появления С. Небольшую программу (скажем, не более 1000 строк) можно заставить из упрямства работать, нарушая все правила хорошего стиля программирования. Однако, действуя так, человек уже не сможет справиться с большой программой. Если у вашей программы в 10000 строк плохая структура, то вы обнаружите, что новые ошибки появляются в ней так же быстро, как удаляются старые. С++ создавался с целью, чтобы большую программу можно было структурировать таким образом, чтобы одному человеку не пришлось работать с текстом в 25000 строк. В настоящее время можно считать, что эта цель полностью достигнута.
Существуют, конечно, программы еще большего размера. Однако те из них, которые действительно используются, обычно можно разбить на несколько практически независимых частей, каждая из которых имеет значительно меньший упомянутого размер. Естественно, трудность написания и сопровождения программы определяется не только числом строк текста, но и сложностью предметной области. Так что приведенные здесь числа, которыми обосновывались наши соображения, не надо воспринимать слишком серьезно.
К сожалению, не всякую часть программы можно хорошо структурировать, сделать независимой от аппаратуры, достаточно понятной и т.д. В С++ есть средства, непосредственно и эффективно представляющие аппаратные возможности. Их использование позволяет избавиться от беспокойства о надежности и простоте понимания программы. Такие части программы можно скрывать, предоставляя надежный и простой интерфейс с ними.
Естественно, если С++ используется для большой программы, то это означает, что язык используют группы программистов. Полезную роль здесь сыграют свойственные языку модульность, гибкость и строго типизированные интерфейсы в С++ есть такой же хороший набор средств для создания больших программ, как во многих языках. Но когда программа становится еще больше, проблемы по ее созданию и сопровождению перемещаются из области языка в более глобальную область программных средств и управления проектом.
Возможно возникновение подозрения о том, что запись программы с использованием подробной системы типов, увеличит размер текста. Для программы на С++ это не так: программа на С++, в которой описаны типы формальных параметров функций, определены классы и т.п., обычно бывает даже короче своего эквивалента на С, где эти средства не используются. Когда в программе на С++ используются библиотеки, она также оказывается короче своего эквивалента на С, если, конечно, он существует.
Итак, C++ – очень эффективные язык программирования. Этому способствует то, что он является структурированным, что помогает при работе в нем более четко видеть все недостатки программ, написанных программистами. Так же это способствует командной работе, а не созданию программ в одиночку, тем более если программа достаточно большая.
Глава 2. Работа с файлами С++
2.1. Работа с текстовыми файлами
Для работы с файлами в языке С++ имеется набор функций, определенных в библиотеке stdio.h. Перед началом работы с файлом его следует открыть, что достигается с помощью функции fopen(), имеющей следующий синтаксис:
FILE *fopen(const char *filename‚ const chat *mode );
Здесь filename – строка, содержащая путь и имя файла; mode – строка, определяющая режим открытия файла (на чтение или на запись); FILE – специальный тип данных для работы с файлами. Данная функция возвращает значение NULL, если файл не был успешно открыт, иначе – другое значение. Рассмотрим последовательность действий по созданию простого текстового файла на языке С++ и записи в него текстовой информации.3
Пример 1. Запись текстовой информации в файл:
#include“stdafx.h”
#include“stdio.h”
Int main(void)
{
setlocale(LC_ALL, “Russian”);
charstr_file[]=”Строка для файла”;
FILE* fp = fopen(“my_fi1e.txt”,”w”);
if(fp != NULL)
{
printf(“Идет запись информации в файл...\n”);
for(inti=0;i<strlen(str_file);
putc(str_file[i],fp);
}
Else printf(“Невозможно открыть файл на запись.\n”);
fclose(fp);
return 0;
}
В данном примере задается специализированный указатель fp типа FILE, который инициализируется функцией fopen(). Функция fopen() в качестве первого аргумента принимает строку, в которой задан путь и имя файла. Вторым параметром определяется способ обработки файла, в данном случае, значение «w», которое означает открытие файла на запись с удалением всей прежней информации из него. Если файл открыт успешно, то указатель fp не будет равен NULL и с ним возможна работа. В этом случае с помощью функции putc() выполняется запись символов в файл, на который указывает указатель fp. Перед завершением программы открытый файл следует закрыть во избежание в нем потери данных. Это достигается функцией fclose(), которая принимает указатель на файл и возвращает значение 0 при успешном закрытии файла, иначе значение ЕОF.
Теперь рассмотрим пример программы считывания информации из файла.
Пример 2. Считывание текстовой информации из файла:
#include“stdafx.h”
#include“stdio.h”
int main(void)
{
setlocale(LC_ALL, “Russian”);
charstr_file[100];
FILE* fp= fopen(“my_file.txt”,”r”);
if(fp != NULL)
{
Int i =0;
charch;
while((сh = getc(fp)) != ЕОF)
str_file[i++]=ch;
str_file[i] = ‘\0’;
printf(str_file);
}
Else printf(“Невозможно открыть файл на чтение.\n”);
fclose(fp);
return 0;
}
В приведенном листинге функция
fopen() открывает файл на чтение,
что определяется значением второго аргумента
равною «r». Это значит, что в
него невозможно произвести запись данных,
а только считывание. Сначала
выполняется цикл while, в котором из файла
считывается символ с помощью функции
getc() и выполняется проверка: если считанное
значение не равно символу конца файла
ЕОF, то значение переменной сh записывается
в массив str_file. Данный цикл будет выполняться
до тех пор, пока не будут считаны все символы
из файла, т.е. пока не будет достигнут
символ EОF. После завершения цикла формируется
строка str_file, которая выводится на экран
с помощью функции printf(). Перед завершением
программы также выполняется функция
закрытия файла fclose().
Работа с текстовыми файлами через функции putc и getc не всегда удобна. Например, если необходимо записать или считать строку целиком, то желательно иметь функции, выполняющие эту работу. В качестве таковых можно воспользоваться функциями fputs() и fgets() для работы со строками. Перепишем предыдущие примеры с использованием данных функций.
Пример 3. Использование функций fputs() и fgets():
#include“stdafx.h”
#include“stdio.h”
int main(void)
{
charstr_file[]=”Строка для файла”;
FILE* fp = fopen(“mу_filе.txt”‚”w”);
if(fp != NULL)
fputs(str_file,fp);
else printf(“Невозможно открыть файл на запись.\n”);
fclose(fp);
fp = fopen(“mу_file.txt”,”r”);
if(fp != NULL)
{
fgets(str_file,sizeof(str_
printf(fp);
}
fclose(fp);
return 0;
}
Аналогичные Действия по записи данных в файл и считывания информации из него можно выполнить и с помощью функций fprintf() и fscanf(). Однако эти функции предоставляют большую гибкость в обработке данных файла. Продемонстрируем это на следующем примере. Допустим, имеется структура, хранящая информацию о книге: название, автор, год издания. Необходимо написать программу сохранения этой информации в текстовый файл и их считывания. Пример использования данных функций представлен в примере 4.
Пример 4. Использование функций fprintf() и fscanf():
#include“stdafx.h”
#include“stdio.h”
#define N 2
Struct book
{
char name[100];
char author[100];
int year;
}
books [N];
int main(void)
{
for(inti=0;i<N;i++)
{
scanf("%s",books[i].name);
scanf("%s",books[i].author);
scanf("%d",&books[i].year);
}
for(inti=0;i<N;i++)
{
puts(books[i].name);
puts(books[i].auth0r);
printf("%d\n",books[i].year);
}
FILE* fp = fopen(“mу_filе.txt”‚ ”w”);
for(inti=0;i<N;i++)
fprintf(fp,"%s %s %d\n",books[i].name,books[i].
fclose(fp);
fp =fopen("my7file.txt","r");
for(i=0;i<N;i++)
fscanf(fp,"%s %s %d\n“, books[i].name,books[i].author,
fclose(fp);
printf("---------------------—
for(i=0;i<N;i++)
{
puts(books[i].name);
puts(books[i].author);
printf{("%d\n"‚books[i].уеаr);
}
return 0;
}
При выполнении Данной программы вводится информация по книгам в массив структур books и выводится введенная информация на экран. Затем открывается файл my_file.txt на запись, в который заносится информация по книгам в порядке: наименование, автор, год издания. Так как число книг в данном случае равно двум, то выходной файл будет выглядеть следующим образом:
OneginPushkin 1983
OblomovGriboedov 1985
Затем, файл my_file.txt открывается на чтение и с помощью функции scanf() осуществляется считывание информации в элементы структуры. В заключении считанная информация выводится на экран монитора.
Представленный пример показывает возможность структурированной записи информации в файл и ее считывания. Это позволяет относительно просто сохранять разнородные данные в файле для их дальнейшего использования в программах.
При внимательном рассмотрении предыдущих примеров можно заметить, что функции считывания информации из файла «знают» с какой позиции следует считывать очередную порцию данных. Действительно, в последнем примере функция fscanf(), вызываемая в цикле, «знает» что нужно считать сначала первую строку из файла, затем вторую и т.д. И программисту нет необходимости задавать позицию для считывания данных. Все происходит автоматически. Вследствие чего появляется такая особенность работы? Дело в том, что у любого открытого файла в программе, написанной на С++ имеется указатель позиции (номера), с которой осуществляется считывание данных из файла. При открывании файла на чтение номер этой позиции указывает на начало файла. Поэтому функция fscanf(), вызванная первый раз, считывает данные первой строки. По мере считывания информации из файла, позиция сдвигается на число считанных символов. И функция fscanf() вызванная второй раз будет работать уже со второй строкой в файле. Несмотря на то, что указатель позиции в файле перемещается автоматически, в языке С++ имеются функции fscanf() и ftell(), позволяющие программно управлять положением позиции в файле.
Синтаксис данных функций следующий:
Int fseek( FILE *stream‚ long offset, int origin);
Longftell( FILE *stream );
где *stream – указатель на файл; pffset – смещение позиции в файле (в байтах); origin – флаг начального отсчета, который может принимать значения: SEEK_END – конец файла, SEEK_SET – начало файла; SEEK_CUR – текущая позиция. Последняя функция возвращает номер текущей позиции в файле.4
Рассмотрим действие данных функций на примере считывания символов из файла в обратном порядке.
Пример 5. Использование функций fscanf() и ftell():
#include “stdafx.h”
#include “stdio.h”
Int main(void)
{
FILE* fp = fopen("my_file.txt“, “\w”);
if(fp != NULL)
{
Fprint(fp)"Это пример использования функций fseek и ftell");
}
fclose(fp);
fp = fopen(“my_file.txt“,“r”);
if(fp != NULL)
{
charch;
fseek(fp, 0,SEEK_END);
long length = ftell(fp);
printf("1ength = %d\n",1ength);
for(inti = 1;i<= length;i++)
{
fseek(fp,-i, SEEK_END);
ch = getc(fp);
pu tchar(ch);
}
}
fclose(fp);
return 0;
}
В данном примере сначала создается файл, в который записывается строка «Это пример использования функций fseek и ftell». Затем этот файл открывается на чтение и с помощью функции fseek(fp,0,SEEK_END) указатель позиции помещается в конец файла. Это достигается за счет установки флага SEEK_END‚ который перемещает позицию в конец файла при нулевом смещении. В результате функция ftell(fp) возвратит число символов в открытом файле. В цикле функция fseek(fp‚–i‚SEEK_END) смещает указатель позиции на –i символов относительно конца файла, после чего считывается символ функцией getc(), стоящий на i-й позиции с конца.
Так как переменная i пробегает значения от 1 до length, то на экран будут выведены символы из файла в обратном порядке.
Таким образом, данные примеры показывают основы работы с текстовыми файлами в C++. В основе лежат такие функции, как fopen(), putc(), fclose(), fprintf(), fscanf() и мн. др.
2.2 Работа с бинарными файлами
Следует отметить, что во всех рассмотренных выше примерах функция fopen() в режимах «r» и «w» открывает текстовый файл на чтение и запись соответственно. Это означает, что некоторые символы форматирования текста, например, возврат каретки ‘\r’ не могут быть считаны как отдельные символы, их как бы не существует в файле, но при этом они там есть. Это особенность текстового режима файла. Для более «тонкой» работы с содержимым файлов существует бинарный режим, который представляет содержимое файла как последовательность байтов где все возможные управляющие коды являются просто числами. Именно в этом режиме возможно удаление или добавление управляющих символов недоступных в текстовом режиме. Для того чтобы открыть файл в бинарном режиме используется также функция fopen() с последним параметром равным «rb» и «wb» соответственно для чтения и записи. Продемонстрируем особенности обработки бинарного файла на примере подсчета числа управляющих символов возврата каретки ‘\г’ в файле, открытый в текстовом и бинарном режимах.5
Пример 6. Программа подсчета числа символов ‘\r’ в файле:
#include“stdafx.h”
#include“stdio.h”
int main(void)
{
FILE* fp = fopen("my_file.tхt","w");
if(fp ! = NULL)
{
fprintf(fp,“Это\пример использования\nбинарных файлов“);
}
fclose(fp);
charch;
intcnt = 0;
fp = fopen(“my_file.txt“,"r");
if(fp != NULL)
{
while((ch = getc(fp)) != EOF)
if(ch == '\r‘) cnt++;
}
fclose(fp);
printf("Текстовый файл: количество= %d\n“,cnt);
cnt=0;
fp = fopen("my_file.txt",”rb");
if(fp != NULL)
{
while((ch = getc(fp)) != EOF)
if(ch == '\r') cnt++;
}
fclose(fp);
printf("Бинарный файл: количество = %d\n”,cnt);
return 0;
}
Результат работы будет следующий:
Textfile: cnt = 0
Binary file: cnt = 2
Анализ полученных данных показывает, что при открытии файла в текстовом режиме, символы возврата каретки ‘\r’ не считываются функцией getc(), а в бинарном режиме доступны все символы.
Еще одной особенностью текстового формата файла является запись чисел в виде текста. Действительно, когда в предыдущих примерах выполнялась запись числа в файл с помощью функции fprintf(), например, года издательства книги, то число заменялось строкой. А когда она считывалась функцией fscanf(), то преобразовывалась обратно в число. Если мы хотим компактно представлять данные в файле, то числа следует хранить как числа, а не как строки. При этом целесообразно использовать бинарный режим доступа к файлу, т.к. будет гарантия, что любое записанное число не будет восприниматься, как управляющий символ и будет корректно считан из файла.
Для работы с бинарными файлами предусмотрены функции fread() и fwrite() со следующим синтаксисом:
size_tfread( void *buffer, size_t size, size_t count, FILE *stream );
где *buffer – указатель на буфер памяти, в который будут считываться данные из файла; size – размер элемента в байтах; count – число считываний элементов; *stream – указатель на файл.
Size_tfwrite( void *buffer, size_t size, size_t count, FILE *stream );
где *buffer – указатель на буфер памяти, из которого будут считываться данные в файл; size – размер элемента в байтах; сount – число записей; *stream – указатель на файл.6
Приведем пример использования функций fwrite() и fread(),
Пример 7. Использование функций fwrite() и fread():
#include“stdafx.h”
#include“stdio.h”
int main(void)
{
FILE *stream;
char list[30];
inti, numread, numwritten;
if( (stream = fopen( "fread.out", “wb” )) != NULL )
{
for ( i= 0; i< 25; i++)
list[i] = (char)('z' — i);
numwritten =fwrite( list, sizeof( char ), 25, stream );