- •Пояснительная записка
- •Содержание
- •Постановка задачи
- •Выбор решения
- •Определение необходимых модулей программы.Разработанная программа состоит из двух модулей:
- •Описание разработки программы
- •Отладка и тестирование
- •Описание программы
- •Разработка приложения KursorCons.Exe
- •VvodDat()
- •Izmenit(int m)
- •Разработка меню
- •Заключение
- •Список используемых источников
- •Приложение а
Заключение
При выполнении данной курсовой работы были получены навыки разработки многомодульных программ. Были освоены приемы создания псевдографического интерфейса, изучены функции работы с консолью, способы обработки событий от клавиатуры и мыши. Усвоены механизмы реализации меню. Изучены функции работы с файлом. Получены базовые навыки программирования на языке С. Изучены основные возможности среды программирования Visual Studio 2017. Получены навыки отладки и тестирования программ.
В рамках выполнения курсовой работы была написана программа необходимая для создания телефонного справочника. Программа предоставляет небольшой, но достаточный список возможностей. Не требует большого количества системных ресурсов и обеспечивает быструю обработку базы данных.
Не удалось реализовать панель инструментов, т.к. псевдографический интерфейс накладывает ограничения на интерфейс программы.
В дальнейшем программу можно улучшить, добавив в интерфейс горячие клавиши на каждый пункт меню. Улучшить навигацию по базе данных путем добавления постраничного перемещения и сортировки.
Список используемых источников
Керниган Б. Ритчи Д. Язык программирования С. 1985 г.
К. Джамса. Учимся программировать на языке С++. 1997 г.
В. Г. Давыдов. Программирование и основы алгоритмизации. 2003 г.
Приложение а
Листинг программы
#include "stdafx.h"
#include "windows.h"
HANDLE hConsoleOut; /* Дискриптор консоли для вывода */
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; /* Информация о консоли */
COORD Home = { 0,5 }; /*координаты курсора - столбец, строка*/
struct Dat {
int Day;
int Month;
int Year;
};
struct Person {
char Name[80]; //ФИО абонента
char TelNom[14]; //Телефонный номер
struct Dat Podkl; //Дата подключения
char Adr[120]; //Адрес абонента
};
struct Person Sotr, *pS;//Объявляем структуру данных и указатель
FILE * pIN, *pOut;//Указатели для работы с файлами
char NameFile[] = "..\\MyBD.dat";
char NameOldFile[] = "..\\MyBD.Old";//Копия файла до изменений
int NRec;//количество записей
void ClearScreen(void) //Функция очистки консоли и установки курсора
{
//получаем информацию о консоли
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut, &csbiInfo);
::system("cls"); //очищаем консоль
//устанавливаем курсор в позицию Home
::SetConsoleCursorPosition(hConsoleOut, Home);
}
int FileCopy()
{
errno_t err;//переменная для проверки на ошибки
//int k = sizeof(NRec) + sizeof(Sotr)*NRec;//размер файла в байтах
err = fopen_s(&pOut, NameOldFile, "wb");
if (err == 0)
{
int D=NRec;
fwrite(&NRec, sizeof(NRec), 1, pOut);
fseek(pIN, sizeof(NRec), 0);
while (D-- > 0)
{
//fseek(pIN, sizeof(NRec), 0);
fread(&Sotr, sizeof(Sotr), 1, pIN);
fwrite(&Sotr, sizeof(Sotr), 1, pOut);
}
}
else
{
printf("Не удается создать файл для копии\n");
return 1;
}
fclose(pOut);
return 0;
}
void PrintSotr(int N) {
ClearScreen();
printf("Печать %d записи \n", N);
printf("1.ФИО абонента - %s\n", Sotr.Name);
printf("2.Телефонный номер - %s\n", Sotr.TelNom);
printf("3.Дата подключения - %d/%d/%d\n", Sotr.Podkl.Day,
Sotr.Podkl.Month, Sotr.Podkl.Year);
printf("4.Адрес - %s\n", Sotr.Adr);
::system("pause");
}
void AddRec()
{
fseek(pIN, sizeof(NRec)+sizeof(Sotr)*NRec, 0);
fwrite(&Sotr, sizeof(Sotr), 1, pIN);
NRec++;
fseek(pIN, 0, 0);
fwrite(&NRec, sizeof(NRec), 1, pIN);
}
void VvodDat() {
int LEAP;
printf("Введите год=>");
scanf_s("%d", &Sotr.Podkl.Year);
int Y = Sotr.Podkl.Year;
LEAP = Y % 4 == 0 && Y % 100 != 0 || Y % 400 == 0;
printf("Введите месяц=>");
scanf_s("%d", &Sotr.Podkl.Month);
while (Sotr.Podkl.Month < 1 || Sotr.Podkl.Month>12)
{
printf("Неверное значение месяца! ВВедите вновь!=>");
scanf_s("%d", &Sotr.Podkl.Month);
}
printf("Введите день=>");
scanf_s("%d", &Sotr.Podkl.Day);
int MaxDay = 31; int M = Sotr.Podkl.Month;
if (M == 2) MaxDay = 28 + LEAP;
if (M == 4 || M == 6 || M == 9 || M == 11) MaxDay = 30;
while (Sotr.Podkl.Day<1 || Sotr.Podkl.Day>MaxDay)
{
printf("Неверный день для месяца %d\nВведите вновь=>", M);
scanf_s("%d", &Sotr.Podkl.Day);
}
}
void Vvod(/*int N */)//N-номер записи в файле
{
ClearScreen();
printf("Ввод записи об абоненте\n");
printf("Введи ФИО абонента=>");
scanf_s("%39s", Sotr.Name, sizeof(Sotr.Name));
printf("Введи телефонный номер абонента=>");
scanf_s("%39s", Sotr.TelNom, sizeof(Sotr.TelNom));
printf("Введи дату подключения\n");
VvodDat();
printf("Введи адрес=>");
scanf_s("%39s", &Sotr.Adr, sizeof(Sotr.Adr));
AddRec();
}
int ConnectBD() {
errno_t err;//переменная для проверки на ошибки
int k;
err = fopen_s(&pIN, NameFile, "r+b");
if (err != 0) {
printf("Не удалось окрыть файл! Создать новый? Да=1, Нет=0\n=>");
scanf_s("%d", &k);
if (k == 0) return 1;//отказ от создания нового файла
else
{//создание нового файла
err = fopen_s(&pIN, NameFile, "wb");
if (err == 0) {
NRec = 0;
fwrite(&NRec, sizeof(NRec), 1, pIN);
return 0;
}
else {
printf("Не удалось создать файл\n");
return 2;
}
}
}
fread(&NRec, sizeof(NRec), 1, pIN);//чтение количества записей в переменную NRec
return 0;
}
int Menu()
{
ClearScreen();//вызов функции очистки консоли
int t;
printf("\t\t1. Посмотреть записи\n");
printf("\t\t2. Добавить записи\n");
printf("\t\t3. Удалить запись\n");
printf("\t\t4. Исправить запись\n");
printf("\t\t5. Завершить работу БД\n");
printf("\t\t Выбери номер для работы =>");
//запоминаем состояние буфера консоли
GetConsoleScreenBufferInfo(hConsoleOut, &csbiInfo);
scanf_s("%d", &t);
while (t < 1 || t>5)//обработка неверного номера пункта меню
{
//сохраняем координаты курсора для повторного ввода
COORD Home = { csbiInfo.dwCursorPosition.X + 2, csbiInfo.dwCursorPosition.Y };
::SetConsoleCursorPosition(hConsoleOut, Home);
printf("Неверно! попробуйте вновь!");
Sleep(3000);//Задержка на 3 секунды
Home.X -= 2;
::SetConsoleCursorPosition(hConsoleOut, Home);
printf(" ");
::SetConsoleCursorPosition(hConsoleOut, Home);
scanf_s("%d", &t);
}
return t;
}
void LookRec()//просмотр записей
{
ClearScreen();
Home = { 5,2 };
::SetConsoleCursorPosition(hConsoleOut, Home);
printf("Введите номер записи для просмотра\n");
int k;
scanf_s("%d", &k);
while (k<1 || k>NRec)//нет такой записи
{
printf("Такой записи нет в БД.Введите другой номер");
scanf_s("%d", &k);
}
//установка курсора на нужную запись
fseek(pIN, sizeof(NRec) + sizeof(Sotr)*(k - 1), 0);
fread(&Sotr, sizeof(Sotr), 1, pIN);//чтение записи в структуру Sotr
PrintSotr(k);//Вывод прочитанной записи
}
int DeleteRec()
{
printf("Введите номер удаляемой запис=>");
int N,k;
scanf_s("%d", &N);
while (N <1 && N > NRec)
{
printf("Такой записи нет. Введите другой номер=>");
scanf_s("%d", &N);
}
fseek(pIN, sizeof(NRec) + sizeof(Sotr)*(N - 1), 0);
fread(&Sotr, sizeof(Sotr), 1, pIN);//чтение записи в структуру Sotr
PrintSotr(N);
printf("Запись %d будет удалена навсегда!!!Для подтверждения Да=1, Нет=0",N);
scanf_s("%d", &k);
if (k == 0) return 1;
while (N<NRec)
{
fseek(pIN, sizeof(Sotr)*N + sizeof(NRec), 0);
fread(&Sotr, sizeof(Sotr), 1, pIN);
fseek(pIN, sizeof(Sotr)*(N - 1) + sizeof(NRec), 0);
fwrite(&Sotr, sizeof(Sotr), 1, pIN);
N++;
}
NRec--;
fseek(pIN, 0, 0);
fwrite(&NRec, sizeof(NRec), 1, pIN);
return 0;
}
int DelRec()
{
::system("Cls");
printf("\t\tУдаление записей\n");
int k,m;
printf("Создать резервную копию? Да=1, нет=0\n");
scanf_s("%d", &k);
if (k != 0)
if (!FileCopy())
{
printf("Копия создана!\n");
return DeleteRec();
}
else {
printf("Не удалось создать копию!!!\n Все равно продолжить? Да=1, нет=0\n");
scanf_s("%d", &m);
if (m == 0)
{
printf("Не выполняем удаление!!!\n");
return 1;
}
else
return DeleteRec();
}
return DeleteRec();
}
void Izmenit(int m){
switch (m)
{
case 1: {
printf("Ведите новое значение для фамилии\n");
scanf_s("%39s", Sotr.Name, sizeof(Sotr.Name));
break;
}
case 2: {
printf("Введи телефонный номер=>");
scanf_s("%39s", Sotr.TelNom, sizeof(Sotr.TelNom));
break;
}
case 3: {
printf("Введи дату подключения\n");
VvodDat();
break;
}
case 4: {
printf("Введи адрес=>");
scanf_s("%39s", Sotr.Adr, sizeof(Sotr.Adr));
break;
}
}
}
void RecEdit()
{
//функция редактирования записи
int k;//номер записи
int m;//номер пункта
::system("cls");
printf("Введи номер записи для редактирования =>");
scanf_s("%d", &k);
while (k < 1 || k > NRec) {
printf("Неверный номер записи. Введи заново\n");
scanf_s("%d", &k);
}
fseek(pIN, sizeof(NRec) + sizeof(Sotr)*(k - 1), 0);
fread(&Sotr, sizeof(Sotr), 1, pIN);
while (1) {
PrintSotr(k);
printf("Выбери номер пункта для исправления или 0 для окончания");
scanf_s("%d", &m);
while (m < 0 || m>4)//всего 4 поля в структуре Sotr
{
printf("число должно быть от 0 до 4!Введите вновь!\n");
scanf_s("%d", &m);
}
if (m > 0 && m < 5)
//изменения в записи
Izmenit(m);
if (m == 0)//конец редактирования
{
printf("Сохранить изменения? Да-1 нет-0=>");
scanf_s("%d", &m);
if (m == 0) return;
fseek(pIN, sizeof(NRec) + sizeof(Sotr)*(k - 1), 0);
fwrite(&Sotr, sizeof(Sotr), 1, pIN);
return;
}
}
}
int main()
{
::system("CHCP 1251");
int m;
int k = ConnectBD();//открываем файл с БД для чтения и записи
if (k != 0) return k;//аварийное завершение программы
printf("файл БД готов к работе\nВ БД записей=%d\n ",NRec);
::system("pause");
while (k = Menu())//цикл продолжается до тех пор, пока не выбран 5 пункт
{
switch (k)
{
case 1:
LookRec(); break;
case 2:
Vvod(); break;
case 3://вызов функции удаления записи
{
m = DelRec();
if (m != 0) printf("Запись не удалена\n");
::system("pause"); break;
}
case 4://вызов функции исправления записи
RecEdit(); break;
case 5:
fclose(pIN); return 0;//завершение работы
default:
break;
}
}
::system("pause"); return 0;
}