Структуры, объединения и списки. Файловый ввод-вывод
Определить структурированный тип, определить набор функций для работы с массивом структур. В структурированной переменной предусмотреть способ отметки ее как не содержащей данных (т.е. "пустой"). Функции должны работать с массивом структур или с отдельной структурой через указатели, а также при необходимости возвращать указатель на структуру. В перечень функций входят:
- «очистка» структурированных переменных;
- поиск свободной структурированной переменной;
- ввод элементов (полей) структуры с клавиатуры;
- вывод элементов (полей) структуры с клавиатуры;
- поиск в массиве структуры и минимальным значением заданного поля;
- сортировка массива структур в порядке возрастания заданного поля (при сортировке можно использовать тот факт, что в Си++ разрешается присваивание структурированных переменных);
- поиск в массиве структур элемента с заданным значением поля или с наиболее близким к нему по значению.
- удаление заданного элемента;
- изменение (редактирование) заданного элемента.
- вычисление с проверкой и использованием всех элементов массива по заданному условию и формуле (например, общая сумма на всех счетах) - дается индивидуально.
Перечень полей структурированной переменной (повариантно):
Вариант 7. Наименование товара, цена, количество, процент торговой надбавки.
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#define BUFF_SIZE 20 // размер массива структур
#define TEXT_LEN 32 // максимальная длина текста в структуре
#pragma argsused
typedef enum // типы полей структуры
{
FT_NAME,
FT_PRICE,
FT_QUANTITY,
FT_PERCENT,
}FIELDTYPE, *LPFIELDTYPE;
typedef struct // структура элемента массива
{
char Name[TEXT_LEN]; // наименование товара
double Price, Percent; // цена и процент торговой надбавки
int Quantity; // количество
}ITEM, *LPITEM;
typedef struct // структура списка (можно создать несколько переменных типа LIST)
{
ITEM Items[BUFF_SIZE]; // массив структур
int Count; // количество используемых элементов
}LIST, *LPLIST;
int check_input_int(char* msg); // ввод числа с проверкой корректности
double check_input_float(char* str); // ввод вещественного числа с проверкой корректности
void item_clear(LPITEM lpItem); // очистка структуры
void list_clear(LPLIST lpList); // очистка списка структур
LPITEM item_find_min(LPITEM Items, int Count, FIELDTYPE ft); // поиск минимального значения по полю ft
void separator(); // разделитель
void table_head(); // вывод заголовка таблицы
void item_out(LPITEM Item); // вывод структуры на экран
void item_in(LPITEM Item); // ввод данных в структуру
void item_edit(LPITEM Item); // редактирование элемента
LPITEM item_find(LPITEM Items, int Count, FIELDTYPE ft, void* value); // поиск наиболее близкого значения поля ft
int list_index_of(LPLIST lpList, LPITEM lpItem); // возвращает индекс элемента
void list_delete(LPLIST lpList, LPITEM lpItem); // удаление элемента из списка
LPITEM list_find(LPLIST lpList, FIELDTYPE ft, void* value); // поиск наиболее близкого значения поля ft
LPITEM list_find_empty(LPLIST lpList); // поиск пустой переменной в списке
void list_sort(LPLIST lpList, FIELDTYPE ft); // сортировки списка структур по полю ft
void list_delete_index(LPLIST lpList, int Index); // удаление из списка элемента с индексом Index
double total_sum(LPLIST lpList); // общее количество
void list_out(LPLIST lpList); // вывод всех не пустых элементов списка
void sort_mode(LPLIST lpList); // режим сортировки
int find_mode(LPLIST lpList); // поиск значения по выбранному полю
void list_edit(LPLIST lpList); // редактор списка структур
void text_generate(char* str, int MaxLen); // генератор случайного текста
void init_list(LPLIST lpList); // инициализация списка случайными значениями
void printrus(char* format,...); // перекодировка в кириллицу
//---------------------------------------------------------------------------
int main()
{
LIST List; // список (массив) структ
srand(time(NULL)); // рандомизация
init_list(&List); // инициализация списка случайными значениями
list_edit(&List); // редактируем список
return 0;
}
//---------------------------------------------------------------------------
// ввод целого числа с проверкой корректности
int check_input_int(char* msg)
{
char str[TEXT_LEN]; // строка ввода
int i, sz;
do
{
printrus("%s", msg); // выводим сообщение
scanf("%s", str); // получаем строку
sz = strlen(str); // размер строки
i = 0; // проверяем все ли символы цифровые (0..9)
while (i < sz && isdigit(str[i])) i++;
}
while(i < sz); // если есть не число, то повторяем ввод
return atoi(str); // возвращаем результат
}
//---------------------------------------------------------------------------
// ввод вещественного числа с проверкой корректности
double check_input_float(char* msg)
{
char str[TEXT_LEN]; // строка ввода
int i, sz;
do
{
printrus("%s", msg); // выводим сообщение
scanf("%s", str); // получаем строку
sz = strlen(str); // размер строки
i = 0; // проверяем все ли символы цифровые (0..9)
while (i < sz && !isalpha(str[i])) i++;
}
while (i < sz);
return atof(str); // возвращаем результат
}
//---------------------------------------------------------------------------
// очистка структуры
void item_clear(LPITEM lpItem)
{
lpItem->Name[0] = 0;
lpItem->Price = 0;
lpItem->Quantity = 0;
lpItem->Percent = 0;
}
//---------------------------------------------------------------------------
// очистка списка структур
void list_clear(LPLIST lpList)
{
int i;
for(i = 0; i < lpList->Count; i++) item_clear(&lpList->Items[i]);
lpList->Count = 0;
}
//---------------------------------------------------------------------------
// поиск минимального значения по полю ft
LPITEM item_find_min(LPITEM Items, int Count, FIELDTYPE ft)
{
int i = 1;
int m = 0; // индекс минимального объекта
switch(ft)
{
case FT_NAME : for(; i < Count; i++)
if( strcmp(Items[m].Name, Items[i].Name) > 0 )
m = i;
break;
case FT_PRICE : for(; i < Count; i++)
if( Items[m].Price > Items[i].Price )
m = i;
break;
case FT_QUANTITY : for(; i < Count; i++)
if( Items[m].Quantity > Items[i].Quantity )
m = i;
break;
case FT_PERCENT : for(; i < Count; i++)
if( Items[m].Percent > Items[i].Percent )
m = i;
break;
default : return 0; // если тип поля неизвестен
}
return &Items[m]; // возвращаем указатель на минимальный элемент
}
//---------------------------------------------------------------------------
// разделитель
void separator()
{
printf("-------------------------------------------------------------------------------\n");
}
//---------------------------------------------------------------------------
// вывод заголовка таблицы
void table_head()
{
separator();
printrus("Наименование\tЦена\tКол-во\tПроцент надбавки\n");
separator();
}
//---------------------------------------------------------------------------
// вывод структуры на экран
void item_out(LPITEM Item)
{
printrus("%s\t", Item->Name);
printrus("%4.2lf\t", Item->Price);
printrus("%i\t", Item->Quantity);
printrus("%4.2lf\n", Item->Percent);
}
//---------------------------------------------------------------------------
// ввод данных в структуру
void item_in(LPITEM Item)
{
int i;
printrus("Наименование[%d]\t= ", TEXT_LEN);
scanf("%s", Item->Name);
Item->Price = check_input_float("Цена\t= ");
do
{
i = check_input_int("Количество\t= ");
}
while(i <= 0);
Item->Quantity = i;
Item->Percent = check_input_float("Процент надбавки\t= ");
}
//---------------------------------------------------------------------------
// редактирование элемента
void item_edit(LPITEM Item)
{
clrscr();
printrus("Редактирование элемента:\n");
table_head(); // заголовок таблицы
item_out(Item); // вывод элемента
separator();
printrus("\nВвод новых данных:\n");
separator();
item_in(Item); // ввод новых данных
}
//---------------------------------------------------------------------------
// поиск наиболее близкого значения поля ft
LPITEM item_find(LPITEM Items, int Count, FIELDTYPE ft, void* value)
{
int l = 0;
int i = 1;
int r = 0;
long d1, d2, d3;
switch(ft)
{
case FT_NAME : l = strlen((char*)value);
for (;i < Count; i++)
if (abs(strncmp(Items[i].Name, (char*)value, l)) <= abs(strncmp(Items[r].Name, (char*)value, l)))
r = i;
break;
case FT_PRICE : for (;i < Count; i++)
if (abs(Items[i].Price - *((double*)value)) <= abs(Items[r].Price - *((double*)value)))
r = i;
break;
case FT_PERCENT : for (;i < Count; i++)
if (abs(Items[i].Percent - *((double*)value)) <= abs(Items[r].Percent - *((double*)value)))
r = i;
break;
case FT_QUANTITY : for (;i < Count; i++)
if (abs(Items[i].Quantity - (int)value) < abs(Items[r].Quantity - (int)value))
r = i;
break;
default : return 0; // если тип поля неизвестен
}
return r < Count ? &Items[r] : 0; // если нашли, то возвращаем указатель на элемент, иначе 0
}
//---------------------------------------------------------------------------
// возвращает индекс элемента
int list_index_of(LPLIST lpList, LPITEM lpItem)
{
int i = 0;
// ищем указатель lpItem в списке lpList
while (i < lpList->Count && &lpList->Items[i] != lpItem) i++;
// если нашли, то возвращаем индекс, иначе -1
return i < lpList->Count ? i : -1;
}
//---------------------------------------------------------------------------
// удаление элемента из списка
void list_delete(LPLIST lpList, LPITEM lpItem)
{
int i = list_index_of(lpList, lpItem);
if (i >= 0) list_delete_index(lpList, i);
}
//---------------------------------------------------------------------------
// поиск наиболее близкого значения поля ft
LPITEM list_find(LPLIST lpList, FIELDTYPE ft, void* value)
{
return item_find(lpList->Items, lpList->Count, ft, value);
}
//---------------------------------------------------------------------------
// поиск пустой переменной в списке
LPITEM list_find_empty(LPLIST lpList)
{
// если в списке есть свободные элементы, то
// возвращаем указатель на первых пустой элемент, иначе 0
return (lpList->Count < BUFF_SIZE) ? &lpList->Items[lpList->Count] : 0;
}
//---------------------------------------------------------------------------
// сортировки списка структур по полю ft
void list_sort(LPLIST lpList, FIELDTYPE ft)
{
int i;
ITEM tmp; // для обмена
LPITEM m; // указатель на минимальный элемент
// цикл сортировки
for (i = 0; i < lpList->Count-1; i++)
{
// поиск минимального по полю ft
m = item_find_min(lpList->Items + i, lpList->Count - i, ft);
// обмен
tmp = lpList->Items[i];
lpList->Items[i] = *m;
*m = tmp;
}
}
//---------------------------------------------------------------------------
// удаление из списка элемента с индексом Index
void list_delete_index(LPLIST lpList, int Index)
{
lpList->Count--;
lpList->Items[Index] = lpList->Items[lpList->Count-1];
}
//---------------------------------------------------------------------------
// общее количество
double total_sum(LPLIST lpList)
{
double sum = 0;
int i;
for (i = 0; i < lpList->Count; i++) sum += lpList->Items[i].Quantity;
return sum;
}
//---------------------------------------------------------------------------
// вывод всех не пустых элементов списка
void list_out(LPLIST lpList)
{
int i;
clrscr();
table_head();
for (i = 0; i < lpList->Count; i++) item_out(&lpList->Items[i]);
separator();
printrus("\t%4.2lf\n", total_sum(lpList));
separator();
printrus("\nколичество элементов = %d", lpList->Count);
}
//---------------------------------------------------------------------------
// режим сортировки
void sort_mode(LPLIST lpList)
{
printrus("выберите поля для сортировки\n");
printrus("n - наименование\nc - цена\nq - количество\np - процент надбавки\n");
switch (getch())
{
case 'n' : list_sort(lpList, FT_NAME);
break;
case 'c' : list_sort(lpList, FT_PRICE);
break;
case 'q' : list_sort(lpList, FT_QUANTITY);
break;
case 'p' : list_sort(lpList, FT_PERCENT);
break;
}
}
//---------------------------------------------------------------------------
// поиск значения по выбранному полю
int find_mode(LPLIST lpList)
{
static double cena;
static char a[TEXT_LEN];
int d, res = -1;
printrus("выберите поле для поиска\n");
printrus("n - наименование\nc - цена\nq - количество\np - процент надбавки\n");
switch (getch())
{
case 'n' : printrus("наименование = ");
scanf("%s", a);
res = list_index_of(lpList, list_find(lpList, FT_NAME, a));
break;
case 'c' : cena = check_input_float("цена = ");
res = list_index_of(lpList, list_find(lpList, FT_PRICE, &cena));
break;
case 'q' : printrus("количество = ");
scanf("%d", &d);
res = list_index_of(lpList, list_find(lpList, FT_QUANTITY, (void*)d));
break;
case 'p' : cena = check_input_float("процент надбавки = ");
res = list_index_of(lpList, list_find(lpList, FT_PERCENT, &cena));
break;
}
return res;
}
//---------------------------------------------------------------------------
// редактор списка структур
void list_edit(LPLIST lpList)
{
int ItemIndex = -1; // текущий индекс элемента
LPITEM lpItem = 0; // выбранный элемент
if (lpList->Count > 0) ItemIndex = 0;
// цикл
while(1)
{
clrscr();
// заголовок
printrus("Редактор списка [кол-во = %d] [макс. кол-во = %d] ", lpList->Count, BUFF_SIZE);
if (ItemIndex < 0) printrus("[не выбрано]\n");
else printrus("[Текущий элемент = %d]\n", ItemIndex);
separator();
// клавиши управления
printrus("q - выход\n");
printrus("a - добавить\n");
printrus("d - удалить\n");
printrus("e - редактировать\n");
printrus("l - показать список\n");
printrus("s = сортировка\n");
printrus("c - очистить список\n");
printrus("f - найти\n");
printrus("b - предыдущий\tn - следующий\n\n");
if (ItemIndex >= 0)
{
table_head();
item_out(&lpList->Items[ItemIndex]);
}
separator();
// обработка клавиш
switch (getch())
{
case 'c' : // очистка списка
list_clear(lpList);
ItemIndex = -1;
break;
case 'b' : // переход на предыдущий элемент
if (ItemIndex > 0) ItemIndex--;
break;
case 'n' : // переход на следующий элемент
if (ItemIndex < lpList->Count -1) ItemIndex++;
break;
case 's' : sort_mode(lpList);
list_out(lpList);
printrus("\nнажмите любую клавишу для возврата в меню");
getch();
break;
case 'f' : ItemIndex = find_mode(lpList);
break;
case 'd' : if (ItemIndex >= 0)
{
list_delete_index(lpList, ItemIndex);
if (ItemIndex >= lpList->Count) ItemIndex = lpList->Count -1;
}
break;
case 'e' : if (ItemIndex >= 0) item_edit(&lpList->Items[ItemIndex]);
break;
case 'a' : // добавление элемента в список
lpItem = list_find_empty(lpList); // поиск пустой структуры в списке
if (lpItem)
{
lpList->Count++;
item_in(lpItem);
ItemIndex = list_index_of(lpList, lpItem);
}
else printrus("нет пустых элементов!");
break;
case 'l' : // отображаем список в виде таблицы
list_out(lpList);
printrus("\nнажмите любую клавишу для возврата в меню");
getch();
break;
case 'q': // выход из программы
exit(1);
break;
}
}
}
//---------------------------------------------------------------------------
// генератор случайного текста
void text_generate(char* str, int MaxLen)
{
int i;
for (i = 0; i < 3 + (rand() % (MaxLen-3)); i++) str[i] = 'a' + (rand() % ('z' - 'a'));
}
//---------------------------------------------------------------------------
// инициализация списка случайными значениями
void init_list(LPLIST lpList)
{
int i;
lpList->Count = 10;
for (i = 0; i < lpList->Count; i++)
{
lpList->Items[i].Quantity = rand() % 10000;
lpList->Items[i].Percent = rand() % 100;
lpList->Items[i].Price = (rand() % 100) + ((double)(rand() % 1000) / 1000);
text_generate(lpList->Items[i].Name, TEXT_LEN);
}
}
//---------------------------------------------------------------------------
// выводим на экран кириллицу
void printrus(char* format,...)
{
char buf[254];
va_list ptr;
CharToOem(format,buf);
va_start(ptr,format);
vprintf(buf,ptr);
}
//---------------------------------------------------------------------------
|