Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Основы разработки программ на языке С++ для систем информационной безопасности. Учебное пособие
.pdf
Лабораторная работа № 5
111
Когда в буфере хранятся данные и программа преждевременно завершает своё выполнение (либо в результате сбоя, либо путём вызова метода
exit()), деструкторы классов файлового ввода/вывода не выполняются,
файлы никогда не закрываются, буферы не очищаются и данные теряются
навсегда. Вот почему хорошей идеей является явное закрытие всех открытых файлов перед вызовом exit().
Также буфер можно очистить вручную, используя метод
ostream::flush() или отправив std::flush в выходной поток.
Конструкторы файлового потока принимают необязательный второй
параметр, который позволяет указать программисту способ открытия файла.
В качестве этого параметра можно передавать следующие флаги (которые
находятся в классе ios):
app – открывает файл в режиме добавления;
ate – переходит в конец файла перед чтением/записью;
binary – открывает файл в бинарном режиме (вместо текстового ре-
жима);
in – открывает файл в режиме чтения (по умолчанию для ifstream);
out – открывает файл в режиме записи (по умолчанию для ofstream);
trunc – удаляет файл, если он уже существует.
Лабораторная работа № 5
Разработка консольных приложений для обработки строк
Задание: разработать программу, запрашивающую у пользователя
текстовые данные, выполняющую требуемую обработку и выводящую результат на экран. В табл. 80 приведены варианты индивидуальных заданий.
Таблица 80
Варианты для лабораторной работы № 5
№
вар.
Запрос
Содержание обработки
1
Произвольное предложение
Подсчитать число предлогов
2
Произвольное предложение
Подсчитать число знаков препинания
3
Произвольное предложение
Подсчитать число гласных
4
Произвольное предложение
Подсчитать число согласных
5
Произвольное предложение
Подсчитать количество слов, не считая предлоги

Лабораторные работы
112
Окончание табл. 80
№
вар.
Запрос
Содержание обработки
6
Произвольное предложение
Подсчитать число вхождений в предложение одного их четырех заданных заранее слов
7
Имя файла в виде
сервер:том \каталог1 \каталог2
\…имя. расширение
Ввести по отдельности имя файла,
сервера и всех каталогов
8
Имя файла в виде сервер: том\каталог1\каталог2\…имя. расширение
Подсчитать глубину вложенности
подкаталогов
9
Два имени файла в виде сервер:
том\ каталог1 \каталог2 \…имя.
расширение
Определить, находятся ли они в одноименных подкаталогах и сколько
таких подкаталогов
10
Интернет-адрес файла в виде
http://www.сервер.ru\каталог1\каталог2\…имя. расширение
Ввести по отдельности имя файла,
сервера и всех каталогов
11
Интернет-адрес файла в виде
http://www.сервер.ru\каталог1\каталог2\…имя. расширение
Подсчитать глубину вложенности
подкаталогов
12
Интернет-адреса двух файлов в
виде http://www.сервер.ru\каталог1\каталог2\…имя. расширение
Определить, находятся ли они в одноименных подкаталогах и сколько
таких подкаталогов
Методические указания
Для построения программы понадобятся функции обработки строк,
объявленные в заголовочном файле string.h. Ниже показаны основные необходимые функции, показанные в табл. 81.
Таблица 81
Функции обработки строк
Имя
Примечания
char *strcat(char *dest, const char *src);
дописывает строку src в конец dest
char *strncat(char *dest, const char
*src, size_t);
дописывает не более n начальных символов
строки src (или всю src, если ее длина
меньше) в конец dest

Лабораторная работа № 5
113
Окончание табл. 81
Имя
Примечания
char *strchr(const char *, int);
ищет символ в строке, начиная с головы, и
возвращает его адрес, или NULL, если не
найден
char *strrchr(const char *, int);
ищет символ в строке, начиная с хвоста, и
возвращает его адрес, или NULL, если не
найден
int strcmp(const char *, const char *);
лексикографическое сравнение строк (возвращает "0", если строки одинаковые, положительное, если первая строка больше, и
отрицательное, если меньше)
int strncmp(const char *, const char *,
size_t);
лексикографическое сравнение первых n
байтов строк
char *strcpy(char *toHere, const char
*fromHere);
копирует строку из одного места в другое
char *strncpy(char *toHere, const char
*fromHere, size_t n);
копирует до n байт строки из одного места
в другое
size_t strlen(const char *);
возвращает длину строки
char *strstr(const char *haystack, const
char *needle);
находит первое вхождение строки needle в
haystack
Пример использования функции:
#include <string.h>
#include <stdio.h>
int main()
{
char *str = "строка симоволов";
char buf[32];
memset(buf, 0, sizeof(buf));// заполнение массива 0
printf("строка: \"%s\"\n\n", str);
printf("массив перед копированием: \"%s\"\n", buf);
strcpy(buf, str);
printf("массив после копирования: \"%s\"\n", buf);
return 0;
}

Лабораторные работы
114
ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ
Имеется информация о клиентах телефонной компании и предоставляемых им услугах. Каждая услуга имеет собственный тариф, а каждый
клиент может пользоваться произвольным набором услуг в течение ограниченного интервала времени (соответственно срокам договора). Имеются
данные о фактическом использовании услуг. Вся указанная информация
представлена текстовыми файлами, структура которых выглядит следующим образом.
Файл информации о клиентах содержит фамилию, имя, отчество клиента, номер телефона, дату заключения договора, дату окончания договора,
размер задолженности, допустимый кредит. Каждое поле отделяется запятой,
запись – это строка текста. Пример содержимого в файле следующий:
Иванов Иван Иванович, 9773672365, 12.10.2012, 12.10.2014,0,0
Петров Иван Васильевич, 9734672311, 22.01.2008,
01.11.2011,210,200
Васильев Илья Васильевич, 9714679805, 05.09.2010,
01.12.2012,0,2000
Файл информации об услугах состоит также из записей, состоящих
из полей, разделенных запятыми. Каждая запись включает наименование
услуги, ее код, тариф (в рублях), временной интервал измерения (мин,
сутки, месяц. Если временной привязки нет, ставится символ #). Пример
данных в файле:
Cвязь внутри сети, 1, 0.30, мин
СМС, 2, 0.15, #
Cвязь с другими мобильными сетями, 3, 0.50, мин
Роуминг, 4, 10, мин
Международный тариф, 5, 50, мин
Файл информации об услугах, оказанных клиентам, включает в себя записи, состоящие из полей номера телефона, кода услуги, даты и времени ее
использования в секундах. Знак # используется в случае, если время не определяется (например, отправляется СМС). Пример содержимого в файле:
9734672311, 1, 13.02.2008 13:01:55, 300
9734672311, 2, 28.11.2012 01:32:30, #
9757282392, 5, 23.09.2013 19:14:00, 54

Общие требования к разработке
115
Задание состоит в разработке программы, которая считывает настро-
ечные параметры и формирует отчет по имеющимся данным в файлах. Отчет
записывается в текстовый файл. Число записей в каждом из описанных выше
файлов произвольно.
Общие требования к разработке
Каждый файл хранится в том же каталоге, что и разработанная про-
грамма.
Формат файлов текстовый, каждый из них может быть создан тексто-
вым редактором.
Содержание файла настройки определяется вариантом в таблице ин-
дивидуальных заданий (см. ниже).
Параметры настройки записываются в текстовый файл с именем
Param.ini. Каждый параметр – в отдельной строке.
Результирующий отчет записывается в файл с именем Report.txt. Если
информация отсутствует, вывести в файл строку «Нет данных».
Вывести сообщение в окно программы о результатах её выполнения
– есть или отсутствуют данные в результирующем файле. Язык сообщения
английский либо русский на транслите.
Формат данных в файле Report.txt: каждая строка списка отделяется
символами перевода строки. Если в строке несколько полей, они разделяются символами « , ».
Пример выполнения индивидуального задания
Таблица 82
Нулевой вариант индивидуального задания
№
Отчёт
Параметры
0
Для заданного номера телефона сформировать список предоставленных
услуг, суммарная стоимость которых
не меньше заданной, в течение 3-х последних дней (от момента запуска программы)
Суммарная стоимость, номер
телефона

Индивидуальное задание
116
Рис. 29. Пример содержимого файла uslugi.txt
Рис. 30. Пример содержимого файла ispol.txt
Рис. 31. Пример содержимого файла param.ini
Создание соответствующих структур для каждого файла:
struct VVOD // файл param.ini
{
int sum; // cуммарная стоимость всех услуг
char Nomer[15]; // считывается заданный номер
};
struct SpisokISPLUslug // файл ispol.txt
{
char TELUSE[15]; //номер телефона пользователя
int Kod; //это номер услуги
int Day; // день
int Mes; // месяц

Общие требования к разработке
117
int Yr; //год
int Chas;
int min;
int sec;
int vremispol; // а это время использования услуги
};
Создание массива из структур:
INFTARIF InfTarif[5];
USERINF Pols[10];
SpisokISPLUslug IspUsl[20];
VVOD zadanie;
Создание файлов в программе, открытие их для чтения из файла в
структуры следующим алгоритмом:
FILE *Klient;
errno_t raz = fopen_s(&Klient, "C:\\Users\\acer\\Desktop\\ИЗ\\Project1\\user details.txt", "r");
FILE *Tarif;
errno_t dva = fopen_s(&Tarif, "C:\\Users\\acer\\Desktop\\ИЗ\\Project1\\uslugi.txt", "r");
FILE *IspUslug;
errno_t tri = fopen_s(&IspUslug, "C:\\Users\\acer\\Desktop\\ИЗ\\Project1\\ispol.txt", "r");
FILE *input;
errno_t chetiri = fopen_s(&input, "C:\\Users\\acer\\Desktop\\ИЗ\\Project1\\param.ini", "r");
if (raz || dva || tri || chetiri)
{
printf_s("Не все файлы существуют или имеют некорре-
ткный набор данных\n");
return -1;
}
for (int i = 0; (i < 10) && !feof(Klient); i++)
{
fscanf_s(Klient, "%[^,]s", &Pols[i].Name, 40); fscanf_s(Klient,
"%*c");
fscanf_s(Klient, "%[^,]s", &Pols[i].TelUse, 15);
fscanf_s(Klient, "%*c");

Индивидуальное задание
118
fscanf_s(Klient, "%[^,]s", &Pols[i].PODKL, 12);
fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%[^,]s", &Pols[i].OTKL, 12);
fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%[^,]s", &Pols[i].DOLG, 20);
fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%d", &Pols[i].Balans); fscanf_s(Klient,
"%*c");
}
for (int i = 0; (i < 5) && !feof(Tarif); i++)
{
fscanf_s(Tarif, "%[^,]s", &InfTarif[i].Nazvanie, 40);
fscanf_s(Tarif, "%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].Kod); fscanf_s(Tarif,
"%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].Tarif); fscanf_s(Tarif,
"%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].vremuspol); fscanf_s(Tarif,
"%*c");
}
for (int i = 0; (i < 20) && !feof(IspUslug); i++)
{
fscanf_s(IspUslug, "%[^,]s", &IspUsl[i].TELUSE, 15); fscanf_s(IspUslug, "%*c");
fscanf_s(IspUslug, "%d", &IspUsl[i].Kod); fscanf_s(IspUslug, "%*c");
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Day);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Mes);
fscanf_s(IspUslug, "%d", &IspUsl[i].Yr); fscanf_s(IspUslug, "%*c");
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Chas);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].min);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].sec);
fscanf_s(IspUslug, "%d", &IspUsl[i].vremispol);
if (IspUsl[i].vremispol < 0)
{
IspUsl[i].vremispol = -1;
fscanf_s(IspUslug, "%*c");
}
fscanf_s(IspUslug, "%*c");
}
fscanf_s(input, "%d", &zadanie.sum);

Общие требования к разработке
119
fscanf_s(input, "%*c");
fscanf_s(input, "%s", &zadanie.Nomer, 15);
Алгоритм для определения даты и расчёта задолжности:
for (int j = 0; j < 10; j++)
{
if (((IspUsl[j].Mes - 1) < timeinfo->tm_mon) && ((timeinfo->tm_year 100 + 2000) == IspUsl[j].Yr))
{
h = MessDay[IspUsl[j].Mes - 1] - IspUsl[j].Day + timeinfo->tm_mday;
if (h <= 3)
{ {
if (memcmp(zadanie.Nomer, IspUsl[j].TELUSE, 12) == 0)
{
if (IspUsl[j].Kod == 1)
{
k += InfTarif[0].Tarif*((IspUsl[j].vremispol + 59) / 60); a++;
}
if (IspUsl[j].Kod == 2)
{
k += InfTarif[1].Tarif*((IspUsl[j].vremispol + 59) / 60); b++;
}
if (IspUsl[j].Kod == 3)
{
k += InfTarif[2].Tarif*((IspUsl[j].vremispol + 59) / 60); c++;
}
if (IspUsl[j].Kod == 4)
{
k += InfTarif[3].Tarif*((IspUsl[j].vremispol + 59) / 60); d++;
}
if (IspUsl[j].Kod == 5)
{
k += InfTarif[4].Tarif; e++;
}
}
}
}
}
else if (((IspUsl[j].Mes - 1) == timeinfo->tm_mon) && ((timeinfo>tm_year - 100 + 2000) == IspUsl[j].Yr))

Индивидуальное задание
120
{
h = timeinfo->tm_mday - IspUsl[j].Day;
if (h <= 3)
{
{
if (memcmp(zadanie.Nomer, IspUsl[j].TELUSE, 12) == 0)
{
if (IspUsl[j].Kod == 1)
{
k += InfTarif[0].Tarif*((IspUsl[j].vremispol + 59) / 60); a++;
}
if (IspUsl[j].Kod == 2)
{
k += InfTarif[1].Tarif*((IspUsl[j].vremispol + 59) / 60); b++;
}
if (IspUsl[j].Kod == 3)
{
k += InfTarif[2].Tarif*((IspUsl[j].vremispol + 59) / 60); c++;
}
if (IspUsl[j].Kod == 4)
{
k += InfTarif[3].Tarif*((IspUsl[j].vremispol + 59) / 60); d++;
}
if (IspUsl[j].Kod == 5)
{
k += InfTarif[4].Tarif; e++;
}
}
}
}
}
}
Вывод полученных результатов в файл output и закрытие всех файлов:
if (k >= zadanie.sum)
{
if (a > 0) fprintf_s(output, "Связь внутри сети\n");
if (b > 0) fprintf_s(output, "CMC\n");
if (c > 0) fprintf_s(output, "Связь с другими сетями\n");
if (d > 0) fprintf_s(output, "Роуминг\n");
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
