Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Массивы указателей на строки

Поиск

Задание 1. Текстовый редактор

Задание 1.1 Динамическая память. Модульное программирование

Разработать программный модуль, который предоставляет пользователю выполнять набор определенных операций со строками. При этом реализация способа хранения строк должна быть скрыта от пользователя.

Строки хранятся в виде массива указателей на char. Память под строки выделяется динамически. Задается максимальный размер массива указателей на строки и указатель на первое свободное место в массиве.

#define MAX 100

typedef char* T;

T m[MAX];

T* cur=m;

Набор операций включает добавление новой строки, удаление, замену, поиск, сортировка, разбиение строки на слова, соединение слов в одну строку, освобождение памяти под все строки. Набор операций может быть реализован при помощи функций, декларации которых приводятся ниже.

 

При правильном модульном построении программы отсутствует необходимость в декларациях в заголовочных файлах переменных раскрывающих детали реализации. Все необходимое для работы с данными содержится в функциях, представляющих интерфейс модуля. Декларации функций помещаются в заголовочный файл с расширением.h. В этом случае при замене реализации функций, находящихся в файле с расширением.срр, код остальной части программы останется неизменным. В начале файла реализации следует с помощью директивы #include подключить заголовочный файл. Это позволяет исключить возможные ошибки, поскольку компилятор получает возможность находить несоответствие в декларации и определении одних и тех же функций.

В качестве элементов массива могут быть использованы любые типы данных. Для реализации операций поиска, замены и сортировки необходима функция сравнения элементов. Для реализации операции замены необходима функция, создающая копию элемента в динамической памяти. Для уменьшения зависимости кода от используемого типа данных элементов массива обозначим тип элементов через Т, а функции реализуем в виде модуля

Заголовочный chars.h,

char* copy(char* s);

void dispose (char* s);

int equal(char*s1,char*s2);

int cmp(char*s1,char*s2);

int input();

void output();

Файл реализации chars.cpp

#include "stdafx.h"

#include "chars.h"

char* copy(int first,int last, char* s)

{char* p=new char[last-first+1];

char*begin=p;

while(first!=last)

*p++=s[first++];

*p='\0';

return begin;

}

char* copy(char* s)

{return copy(0,strlen(s),s);}

 

void dispose(char* s)

{delete [] s;}

 

int equal(char*s1,char*s2)

{return strcmp(s1,s2)==0;}

 

int cmp(char*s1,char*s2)

{return strcmp(s1,s2);}

 

Данные, описывающие способ хранения строк, определяются в файле реализации с ключевым словом static. В результате они становятся недоступны в других файлах программы.

Таким образом, файлы представляющие модуль таблицы строк должны выглядеть следующим образом:

 

Заголовочный Tabl.h, содержащий декларации функции для работы со строками

#include "chars.h"

#define MAX 100

typedef char* T;

T*begin();//возвращает указатель на начало массива

T*end(); //возвращает указатель на первое свободное место в массиве cur

int length();

T* insert(const T& item);

Добавление: Проверяет наличие свободного места в таблице, добавляет элемент в таблицу на первое свободное место, затем сдвигает указатель на первое свободное место (cur) на следующую позицию.

T* erase(T* pos);

Удаление: удаляет элемент,на который указывает pos из таблицы. Для этого предварительно проверяет принадлежность pos заполненной части таблицы, затем освобождает память, выделенную под элемент, затем уменьшает текущее количество записей в массиве на единицу и сдвигает элементы с позицией, большей чем pos, на одну позицию влево.

void clear();

Очистка: Предоставляет всю выделенную память для повторного использования

int remove(const T& item);

Удаление: удаляет все элементы, совпадающие с заданным. Возвращает количество удаленных элементов

int find(const T& item);

Поиск: Возвращает указатель на первый элемент, совпадающий с заданным.

int replace(const T&Old,const T&New);

Замена:

Заменяет все вхождения элемента Old на элемент New. Возвращает количество замен

void sort();

Сортировка

 

Файл реализации Tabl.cpp

#include "stdafx.h"

#include "Tabl.h"

static T m[MAX];

static T* cur=m;

T*begin(){return m;}

T*end() {return cur;}

int length(){return cur-m;}

 

T* insert(const T& item)

{if(length()<MAX)

*cur++=copy(item);

return cur;

}

T* erase(T* pos)

{ T* i;

dispose(*pos);

for(i=pos;i<cur;i++)

*i=*(i+1);

cur--;

return pos;}

void clear()

{T* i;

for(i=m;i<cur;i++)

dispose(*i);

cur=m;

}

int remove(const T& item)

{T* i,*j=m; int n=0;

for(i=m;i<cur;i++)

if(!equal(*i,item)

*j++=*i;

else {dispose(*i); n++;}

cur=j;

return n;

}

int find(const T& item)

{T* i;

for(i=m;i<cur;i++)

if(equal(*i,item)) return i-m;

return -1;

}

 

int replace(const T&Old,const T&New)

{T* i;int count=0;

for(i=m;i<cur;i++)

if(equal(*i,Old))

{ dispose(*i);

*i=copy(New);

count++;}

return count;

}

void sort(){}

 

В файле основной программы производится тестирование функций работы со строками. Для этого организуется меню, каждый пункт которого служит для вызова соответствующей функции.

Файл Main.cpp

 

#include "stdafx.h"

#include "Tabl.h"

using namespace std;

 

const int size=256;

char buf[size];

char buf2[size];

 

bool input(T item)

{ return cin.getline(item,size,'\n');}

void output(T item)

{ cout<<item<<endl;}

 

int input()

{

int count;

for(count =0; count <MAX && input (buf); count ++)

insert(buf);

return count;

}

void output()

{T* i;

for(i=begin();i!=end();i++)

output(*i);

}

 

int _tmain(int argc, _TCHAR* argv[])

{char c,endline;

do

{ cout<<"for get case input namber and press enter"<<endl;

cout<<" 0 - exit"<<endl;

cout<<" 1 - input elements"<<endl;

cout<<" 2 - output elements"<<endl;

cout<<" 3 - find "<<endl;

cout<<" 4 - erase"<<endl;

cout<<" 5 - remove"<<endl;

cout<<" 6 - replace"<<endl;

cout<<" 7 - sort"<<endl;

cin.get(c);

cin.get(endline);

switch(c){

case '1':

{ cout<<"input elements: "<<endl;

input();cin.clear();

break;}

case '2':

{ cout<<" elements: "<<endl; output();break;}

case '3':

{ cout<<" input element for find"<<endl;

input(buf);

int i=find(buf);

if(i>=0) cout<<"position = "<<i<<endl;

else cout<<"no found"<<endl;

break;}

case '4':

{ cout<<" input position for erase"<<endl;

int pos; cin>>pos;cin.get(endline);

erase(begin()+pos);break;}

case '5':

{cout<<" input element for remove"<<endl;

input(buf);

int i=remove(buf);

if(i==0) cout<<"no found"<<endl;

break;}

case '6':

{ cout<<" input OLD element for replace"<<endl;

input(buf);

cout<<" input NEW element for replace"<<endl;

input(buf2);

int i=replace(buf,buf2);

if(i==0) cout<<"no found"<<endl;break;}

case '7':

{ sort(); break;}

}

}while(c!='0');

return 0;

}

Задание на разработку модуля функций работы со строками

Заголовки функций содержат дополнительные параметры по сравнению с базовым вариантом, приведенным выше.

first- индекс (указатель) начала диапазона элементов массива, для которого необходимо выполнить функцию.

last- индекс (указатель) конца диапазона элементов массива, для которого необходимо выполнить функцию. Элемент с индексом last в диапазон не включается.

first_item - индекс (указатель) начала диапазона, last_item индекс (указатель) конца диапазона внешнего массива, из которого извлекаются элементы, участвующие в операциях

Вариант 1

int insert(int pos,const T&);

int remove(int first,int last,const T&);

int find (int first, int last,const T& item);

int erase(int first, int last);

int replace (int first,int last,const T&Old,const T&New);

void sort (int first, int last);

Вариант 2

int insert(int first_item,int last_item);

int remove(int first,int last,const T&);

int find (int first, int last,const T& item);

void clear(int first,int last);

int replace (int first,int last,const T&Old,const T&New);

void sort (int first, int last);

Вариант 3

int insert(int pos,int first_item,int last_item);

int remove(int first,int last,int first_item,int last_item);

int find (int first,int last,int first_item,int last_item);

int erase(int first, int last);

int replace (int first,int last,const T&Old,const T&New);

void sort (int first, int last);

Вариант 4

T* insert(T* pos, const T&);

int remove(T* first,T* last,const T&);

T* find (T* first, T* last,const T& item);

T* erase(T* first, T* last);

int replace (T* first,T* last,const T&Old,const T&New);

void sort (T* first, T* last);

Вариант 5

T* insert(T* first_item,T* last_item);

int remove(T* first,T* last,const T&);

T* find (T* first, T* last,const T& item);

void clear(T* first,T* last);

int replace (T* first,T* last,const T&Old,const T&New);

void sort (T* first, T* last);

Вариант 6

T* insert(T* pos,T* first_item,T* last_item);

int remove(T* first,T* last,T* first_item,T* last_item);

T* find (T* first,T* last,T* first_item,T* last_item);

T* erase(T* first, T* last);

int replace (T* first,T* last,const T&Old,const T&New);

void sort (int first, int last);

 

Задание 1.2 Реализация таблицы на основе динамического массива

Определение статического массива

T m[MAX];

заменить на определение указателя

T* m=0;

Динамическое выделение памяти под элементы организовать в функции

Void resize(int n), которая выделяет память под имеющиеся элементы в массиве и дополнительно память под n элементов, копирует в новую память имеющиеся элементы, освобождает ранее выделенную память.

Функция resize используется в функции insert следующим образом

T* insert(const T& item)

{if(length()>MAX) resize(MAX);

//…

}

Задание 1.3 Специальные функции работы со строками

Напишите, используя динамическое выделение памяти, реализации следующих функций:

  1. Char* concate(char* s1, char* s2); Соединяет(сцепляет) две строки
  2. Char* concate(char* s1, char* s2, char* s3); Соединяет(сцепляет) три строки
  3. Char* concate(char* mas[]); Соединяет(сцепляет) массив строк
  4. Char** split(char* s) Разбивает строку на массив подстрок
  5. Char** split(char* s, char* splits); Разбивает строку на массив подстрок, используя массив символов - разделителей
  6. Char* join(char* mas[], char split); Соединяет(сцепляет) массив строк, вставляя между ними символ разделитель

Задание 1.3 Разработка приложения WindowsForms

Отладку и тестирование реализаций функций можно проводить в консольном варианте приложения. Для этого создается проект на основе шаблона WIN32 Console Project. Окончательный вариант разрабатывается как приложение WindowsForms. Интерфейс программы имеет следующий вид:

 

 

 

Исполнение каждой операции начинается после нажатия соответствующей командной кнопки на форме. Ввод данных для формирования строк производится с помощью текстовых полей textBox.

Для конвертирования типа данных String* в тип данных char*можно использовать функции

int copyto(char* buf,String* S,int count);

int copyto(char** str,String* S);

Реализация функции использует функцию программного интерфейса windows WideCharToMultiByte

 

#include <windows.h>

#using <mscorlib.dll>

 

int copyto(char* buf,System::String* S,int count)

{int i, state=0;

for(i=0;i<S->Length;i++){

if(count<=i)break;

wchar_t t=S->Chars[i];

state=WideCharToMultiByte(CP_ACP, 0, &t, 1, &buf[i], 1, NULL, NULL);

}

buf[i]='\0';

return state;}

 

int copyto(char** str,System::String* S)

{ delete [](*str);

*str=new char [S->Length+1];

return copyto(*str,S, S->Length);

}

 

Код занесения данных из текстового поля textBox1 в таблицу будет выглядит следующим образом:

private: System::Void but2_Click(System::Object * sender, System::EventArgs * e)

{char buf [256];

if(textBox1->Text->Length!=0)

{copyto(buf, textBox1->Text,255);

insert(buf));}

listoutput();

}

Просмотр всех строк производится с помощью списка listBox. Для этого можно написать следующую функцию

 

void listoutput()

{listBox1->Items->Clear();

T* i;

for(i=begin();i!=end();i++)

{ String* s=new String(*i);

listBox1->Items->Add(s);

}

Пример разработки программы находится в приложении 1.

 

 

Структуры

Задание 2 Реализация текстового редактора с использованием структур данных

Задание 2.1 Представления набора строк в виде структур данных

Реализовать способ хранения набора строк в виде структуры данных. Продемонстрировать возможность работы с несколькими наборами строк одновременно.

Разработанный в предыдущем задании способ представления данных на основе статического массива обладает рядом недостатков. Функции, работающие со строками, используют конкретное имя массива, поэтому нельзя создать одновременно два набора строк. Для разрешения данной проблемы можно использовать механизм параметров функций. Однако таблица, характеризуется относительно большим числом параметров, что приведет к разрастанию числа аргументов функций.

Другим недостатком использованного способа представления набора строк является невозможность выделения дополнительной памяти в случае заполнения таблицы. Более универсальным является использование динамической памяти для хранения указателей на начало строк. В этом случае таблица вместо статического массива должна содержать указатель на начало участка динамической памяти.

Для того, чтобы иметь возможность работы с несколькими объектами одновременно, представим все данные, связанные со способом хранения строк, в виде одной структуры с полями разных типов. А функциям позволим обрабатывать несколько наборов строк, передав в качестве аргумента указатель на структуру с данными.

Таким образом, файлы, содержащие описание данных и функций для работы со строками, должны выглядеть следующим образом:

Заголовочный chars.

char* init (char* s,int size=256);

char* copy(char* s);

void dispose (char* s);

 

int equal(char*s1,char*s2);

int cmp(char*s1,char*s2);

 

typedef FILE* File;

int input(File f, char *t);

int input(char *t);

void output(File f, char *t);

void output(char *t);

 

заголовочный файл item.h.

#include "chars.h"

typedef char* T;

 

Заголовочный файл Tabl.h

#include "item.h"

struct Tabl{

T* m;

T* cur;

int size;

T buf;

};

Tabl* init(Tabl*i,int sz=10);

Tabl* resize(Tabl*t,int n);

// которая выделяет память под имеющиеся элементы в массиве

//и дополнительно память под n элементов,

//копирует в новую память имеющиеся элементы,

//освобождает ранее выделенную память.

//Функция resize используется в функции insert следующим образом

//T* insert(Tabl* t,const T& item)

//{if(length(t)>t->size) resize(t,t->size);

 

void dispose (Tabl*);

//освобождает выделенную память под элементы

//и под сам массив указателей

T* begin(Tabl*);

T* end(Tabl*);

int length(Tabl*);

T* insert(Tabl**,const T& item);

T* erase(Tabl*,T* pos);

void clear(Tabl*);

int find(Tabl* t,const T& item);

int remove(Tabl* t,const T& item);

int replace(Tabl* t,const T&Old,const T&New);

void sort(Tabl* t);

 

int input(File f,Tabl *t);

int input(Tabl *t);

void output(File f,Tabl *t);

void output(Tabl *t);

void foutput(Tabl *t, char* FileName);

int finput (Tabl *t, char* FileName);

 

Файл реализации Tabl.cpp

# include "Tabl.h”

T*begin(Tabl*t){return t->m;}

T*end(Tabl*t) {return t->cur;}

int length(Tabl*t){return t->cur-t->m;}

 

Tabl* init(Tabl* t, int sz)

{t=new Tabl;

t->buf=0; t->buf=init(t->buf);

t->cur=t->m=new T[t->size=sz];

for(int i=0;i<sz;i++)

t->m[i]=0;

return t;}

 

Tabl* resize(Tabl*t,int n)

{Tabl* tmp=init(t,t->size+n);

T* i;

for(i= begin(t); i!=end(t); i++)

*tmp->cur++=*i;

dispose(t->buf);

delete [] t->m;

delete t;

return tmp;

}

void clear(Tabl*t)

{T* i;

for(i= begin(t); i!=end(t); i++)

dispose(*i);

t->cur=t->m;

}

void dispose (Tabl* t)

{clear(t);

dispose(t->buf);

delete [] t->m;

delete t;}

 

T* insert(Tabl**t,const T& item)

{T tmp= copy(item);

if(length(*t)>=(*t)->size)

*t=resize(*t,(*t)->size);

*(*t)->cur++=tmp;

return (*t)->cur;

}

Ввод данных в таблицу осуществляется с использованием вспомогательного буфера, уназатель на который определен структуре Tabl. Это позволит единообразно организовать ввод для различных типов данных, определяемых при помощи средства typedef.

Память под буфер выделяется динамически в функции

char* init(char* s,int size=256)

{return new char[size];}

Она вызовается при инициализации таблицы

Tabl* init(Tabl* t, int sz)

{t=new Tabl;

t->buf=0; t->buf=init(t->buf);

//…

}

int eof(){return feof(stdin); }

int input(Tabl *t)

{while(!eof())

if(input (t->buf))

insert(&t,t->buf);

return length(t);

}

int input(File f,Tabl *t)

{

while(!eof(f))

if(input (f,t->buf))

insert(&t,t->buf);

return length(t);

}

void output(File f,Tabl *t)

{T* i;

for(i=begin(t);i!=end(t);i++)

output(f,*i);

}

void ExeptionFopen(char* str)

{printf("\n File %s\t open error\n",str);}

 

void foutput(Tabl *t,char* FileName)

{T* i;File f;

if ((f=fopen(FileName,"w"))==0)

{ ExeptionFopen(FileName); return;}

output(f,t);

fclose(f);

}

 

int finput(Tabl*t,char* FileName)

{int count; File f;

if((f =fopen(FileName,"r"))==0)

{ ExeptionFopen(FileName); return 0;}

count=input(f,t);

fclose(f);

return count;

}

Приложение WindowsForms

Для работы с таблицей в файле формы необходимо определить указатель Tabl* t=0; и добавить в обработчик события загрузки формы следующий код

private: System::Void Form1_Load(System::Object * sender, System::EventArgs * e)

{ t= init(t);

//…

}

Реализация функции ExeptionFopen

void ExeptionFopen(char* str)

{String* s=new String(str);

s=String::Concate(S"\nFile",s,S"\t open error\n");

MessageBos::Show(S"ExeptionFopen",s);

 

Задание 2.2 Реализация операций выборки, преобразования и сортировки наборов строк с использованием словаря данных

Словарь данных представляется в виде таблицы. Элементом таблицы является структура, содержащая два поля: соответственно ключ и значение в виде строк. Ключ задает условие для поиска, а значения является результатом поиска.

Struct pair{

T key;

T val;

};

В отличие от поиска операция выборки в качестве результата создает набор строк, удовлетворяющих заданному условию. Условие для выборки удобно задавать в виде указателя на функцию, которая возвращает 1 или 0 в зависимости удовлетворяет строка условию или нет. Тип указателя на функцию определяется следующим образом

typedef bool(*Predicate)(T, void*);

Данные для выборки передаются через аргумент, имеющим тип void*. Для решаемой задачи в качестве параметра используется указатель на таблицу словаря, а в самой функции организуется поиск совпадения подстроки со значением из словаря

Пример реализации функции выборки

Tabl* Query(Tabl*t, Predicate fun,void* param)

{Tabl*rez=new Tabl;

T* i;

for(i= begin(t);i<end(t);i++)

if((*fun)(*i,param))

insert(rez,*i);

return rez;

}

 

Преобразование происходит с полной заменой строки. Замена включает следующие операции:

1) использование промежуточного буфера в динамической памяти,

2) сцепление необходимых частей строк в буфере,

3) освобождение памяти под исходную строку,

4) присваивание указателя на исходную строку указателю на буфер

 

char* concat(const char* a, const char* b)

{char* s=new char[strlen(a)+strlen(b)+1];

strcpy(s,a);

strcat(s,b);

return s;

}

void replace(char *& string, char *OLD, char *NEW)

{

char* p,*temp,*p0;

temp=mycopy("");

int lenOLD = strlen(OLD);

p0=string;

while ((p = strstr(p0, OLD))!= NULL) {

*p=0;

temp=concat(temp, p0);

p0=p+lenOLD;

temp=concat(temp,NEW);

}

temp=concat(temp, p0);

delete [] string;

string= temp;

}

Операция сортировки использует специально разработанную функцию для сравнения строк. Эта функция реализуется согласно условию решаемой задачи.

Варианты задания

  1. Словарь состоит из строк с фамилиями и строк с соответствующими адресами. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих хотя бы одну фамилию из словаря. Преобразовать полученный набор строк таким образом, чтобы после фамилий через пробел был бы указан соответствующий адрес. Произвести сортировку строк по фамилиям (т.е. при сравнении строк учитываются только слова с фамилиями из словаря).
  2. Словарь состоит из строк с названиями городов и строк с соответствующими сокращенными названиями. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих хотя бы одно сокращенное название города. Преобразовать полученный набор строк таким образом, чтобы на месте сокращений стояли полные названия. Произвести сортировку строк по названиям городов.
  3. Словарь состоит из ошибочных слов их исправленных вариантов. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих хотя бы одну ошибку. Исправить ошибки в полученном наборе строк. Исправленные слова выделить заглавными буквами. Произвести сортировку по количеству ошибок в строке.
  4. Словарь состоит из строк с названиями учебных предметов и полученных по этим предметам оценок. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих хотя бы одно название предмета. Преобразовать полученный набор строк таким образом, чтобы после названия предмета через пробел был бы указана соответствующая оценка. Произвести сортировку строк по среднему баллу.
  5. Словарь состоит из строк с названиями товаров и цен. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих все названия товаров. Преобразовать полученный набор строк таким образом, чтобы после названия товара через пробел был бы указана соответствующая цена. Произвести сортировку строк по максимальной цене товара в строке.
  6. Словарь состоит из слов и строки, содержащей количество символов в слове. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих хотя бы одно слово словаря, записанное с обратным порядком символов. Преобразовать полученный набор строк таким образом, чтобы после слова–перевертыша стояло слово из словаря. Произвести сортировку строк по суммарному количеству символов в словах–перевертышах в строке.
  7. Словарь состоит из английских слов и их перевода на русский язык. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих английские слова, которые стоят в том же порядке, что и в словаре. В полученном наборе строк сделать перевод на русский язык. Произвести сортировку строк по количеству английских слов
  8. Словарь состоит из слов в именительном и родительном падеже. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, в которых слова из словаря повторяются более одного раза. Сменить падеж слов в полученном наборе. Произвести сортировку строк по максимальному числу повторений слов словаря.
  9. Словарь состоит из строк с фамилиями студентов и строк с номерами групп. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих фамилии студентов из словаря, обучающихся в одной группе. Преобразовать полученный набор строк таким образом, чтобы после фамилий через пробел была указана соответствующая группа. Произвести сортировку строк по группам.
  10. Словарь состоит из строк с фамилиями авторов книг и строк с названиями книг. Фамилии авторов в словаре могут повторяться. Из входного потока сформировать набор строк. Из набора строк сделать выборку строк, содержащих фамилии авторов из словаря. Преобразовать полученный набор строк таким образом, чтобы после фамилии автора через пробел были указаны названия всех книг, которые он написал. Произвести сортировку строк по максимальному количеству книг, написанных авторами.

 

 

Задание 3. Информационная система

Разработать программу, которая позволяет выполнять набор определенных операций с записями, содержащими учетную информацию некоторой предметной области. Набор операций с записями включает добавление новой записи, удаление, замену, поиск, выполнение запросов и сортировку.

Записи хранятся в виде массива указателей на структуру. Память под массив указателей и память под сами записи отводится динамически. Задается максимальный размер массива указателей и текущее количество записей в массиве.

В программе должно быть предусмотрено сохранение всех записей в файл и чтение из файла. При вводе данных необходима проверка их корректности.

Отладку и тестирование реализаций функций можно проводить в консольном варианте приложения. Окончательный вариант разрабатывается как приложение WindowsForms.

Варианты задания отличаются видом учетной информации и предметной областью.

 

1. Накладная склада. Название, количество и цена товара; название и e-mail фирмы-поставщика; имя кладовщика; дата поступления на склад.

2. Квитанция ломбарда. Название и цена драгоценности; имя и телефон клиента; название и адрес ломбарда; дата приема драгоценности.

3. Экзаменационная ведомость. Имя, номер группы и телефон студента; название предмета; имя и e-mail преподавателя; дата сдачи экзамена, оценка.

4. Приказ о зачислении абитуриентов. Имя и адрес абитуриента; название предмета и оценка экзамена; группа, дата приема, стоимость обучения.

5. Аптечный рецепт. Название и адрес аптеки; имя и телефон врача; лекарство, стоимость, дата выписки рецепта.

6. Квитанция приема у врача. Название и адрес поликлиники; имя и телефон врача; имя и телефон пациента; стоимость и дата приема.

7. Запись в книге учета постояльцев в гостинице. Имя и адрес постояльца; Цена проживания в сутки, номер и категория гостиничного номера; имя и телефон администратора; даты приезда и отъезда.

8. Данные сделки с недвижимостью. Имя и телефон клиента; адрес местонахождения и вид недвижимости; цена и дата сделки.

9. Квитанция продажи автомобилей. Название и дата выпуска автомобиля; Название и адрес автосалона; имя и телефон продавца; дата и цена продажи.

10. Картотека бюро знакомств. Имя, пол, адрес и телефон клиентов. Название и адрес бюро знакомств; стоимость услуги, дата подачи заявки.

11. Картотека биржи труда. Имя и телефон безработного; название, адрес и e-mail фирмы-работадателя; заработанная плата, дата подачи заявления и дата трудоустройства.

12. Кассовый чек магазина. Название и стоимость товара; название и адрес магазина; имя и телефон продавца; дата продажи.

13. Путевка турагенства. Имя, телефон, домашний адрес туриста; адрес и стоимость маршрута поездки; название адрес и e-mail турагентства; дата отправления и стоимость путевки.

14. Музыкальный диск альбома. Массив записей, состоящих из названия группы и имени исполнителя, названия и времени звучания песни; стоимость и дата выпуска диска; адрес и e-mail фирмы-производителя диска.

15. Кафедра факультета. Массив записей, состоящих из имени, телефона, e-mail, домашнего адреса и зарплаты преподавателей; имя заведующего, телефон и дата образования кафедры.

16. Отдел кадров фирмы. Массив записей, состоящих из имени, телефона, e-mail, домашнего адреса и зарплаты сотрудников; название подразделения, имя начальника, дата поступления на работу.

17. Картотека жилищно-коммунального отдела (ЖКО). Массив записей, состоящих из номера, пощади, стоимости и имени ответственного квартиросъемщика квартиры; адрес и дата постройки дома.

18. Протокол соревнований по легкой атлетике. Массив записей, состоящих из имени, телефона, e-mail и адреса спортсмена, дистанции и показанному времени; дата и адрес места проведения соревнований.

19. Протокол встречи футбольных команд. Массив записей, состоящих из имени, телефона, e-mail и адреса футболистов каждой команды; название и адрес команды; дата, адрес и счет встречи

20. Выставка картин. Массив записей, состоящих из имени, телефона, e-mail и адреса художников и названий представленных ими картин; Адрес проведения и дата выставки.

 

Выполнение задания производится по шагам

Задание 3.1 Модульное программирование

На первом шаге производится разработка структуры данных и проектирование программы с учетом модульного стиля программирования. Разбиение программы на независимые друг от друга модули делает ее структуру более гибкой и легко модифицируемой. Например, это позволит быстро заменить используемую для хранения совокупности записей структуру данных Tabl на другую, а также перейти с консольного варианта программы на программу с оконным графическим интерфейсом.

В отдельный заголовочный файл с именем Record.h помещается описание структуры данных, содержащей учетную информацию некоторой предметной области, и декларации функций для работы со структурой.

Описание структуры данных, которая используется для хранения всех записей, помещается в другой файл Tabl.h. При необходимости использования другого типа контейнера для хранения записей изменения в коде затронут только эту часть программы.

Реализация функций полностью аналогична коду функций в таблице строк

В начале заголовочного файла Tabl.h следует с помощью директивы #include подключить заголовочный файл item.h.

#pragma once

#include "record.h"

typedef Record* T;

//#include "chars.h"

//typedef char* T;

Изменяя этот заголовочный файл можно работать как с таблицей строк, так и с таблицей структур.

 

В качестве примера рассматривается предметная область библиотека.

Файл Record.h

class Record (Запись)

{public:

char* title; // название

char autor[10]; // автор

long number; // инвентарный номер

int price; // цена

 

char name [10]; //имя читателя

long number; // номер читательского билета

char address[40];//адрес читателя

long telephone; // телефон читателя

 

char bname [10]; //имя библиотекаря

int day,month,year; // дата выдачи читателю

};

Record* init(Record*); // выделяет память под структур Record

//и инициализирует ее значениями по умолчанию

Record* copy(Record*); //coздает копию структуры Record в динамической памяти

void dispose (Record*); // Освобождает выделенную память под структур Record

int validate(Record*); // проверяет корректность данных

int equal(Record*, Record*); // функция, проверяющая равенство значений полей записей. Используется при поиске

int cmp(Record*, Record*); // функция, сравнивающая записи Используется при сортировке

 

int input(File fp,Record* r);

int input(Record* r);

int output(File f,Record* r);

void output(Record* r);

 

В файл Record.cpp помещаются реализации функций

#include "Record.h"

 

Задание 3.2 Работа с и динамической памятью

На втором шаге реализуются функции, работающие с динамической памятью.

 

Record* init(Record* r) // выделяет память под структур Record

//и инициализирует ее значениями по умолчанию

{ r=new Record;

r->autor[0]='\0';

r->title=0;

r-> number=0;

r->price=0;

r->day=0;r->month=0;r->year=0;

return r;

}

Record* copy(Record* t)//coздает копию структуры Record в динамической памяти

{Record* r=init(t);

strcpy(r->autor,t->autor);

r->title=new char[strlen (t->title)+1];

strcpy(r->title, t->title);

r-> number=t-> number;

r->price=t->price;

r->day= t->day;r->month=t->month; r->year=t->year;

return r;}

 

void dispose (Record* t) // Освобождает выделенную память под структур Record

{if(t)

delete [] t->title;

delete t;}

Задание 3.3 Ввод и вывод

 

Ввод и вывод лучше организовать в виде собственного набора функций, интерфейс которого приведен ниже. Это позволит сделать код программы независмым от используемых в реализации функции библиотечных средств ввода вывода. Например, можно использовать стандартную библиотеку языка Си или потоки языка С++

Для функций ввода используем имя input, для функций ввода – output, например

int input(File fp,Record* r);

int input(Record* r);

void output(File f,Record* r);

void output(Record* r);

Тип File определяется с помощью средства typedef

Например

typedef FILE* File;

Функции возвращают 1 при успешном вводе и 0 в случае ошибки или конца файла. Достижение конца файла можно определит при помощи функции

int eof(FILE* fp){return feof(fp);}

Для повторного ввода файла необходимо вызвать функцию

void clear(FILE* fp){rewind(fp);}

 

Для записи и чтения структуры Record из файла проще всего использовать функции блокового ввода вывода стандартной библиотеки языка Си.

Например

int finput(FILE* f, Record* r)

{return fread(r,sizeof(Record),1,f); }

Такой подход имеет существенное преимущество. Поскольку каждая запись будет иметь одинаковый размер, то можно организовать произвольный доступ к любой записи по ее номеру.

Однако для строковых полей это может привести к не экономному расходованию памяти на диске, так как строки реально могут быть значительно меньше, чем объем зарезервированной под них памяти. Кроме того, при использования указателей в качестве полей структур, применение функций блокового ввода вывода теряет смысл. В этом случае наиболее удобны функции форматного ввода вывода.

 

int finput(File f,Record* r)

{

char buf[256];

int state= fscanf(f,"%s%s%d%d%d%d%d\n",

r->autor,buf,&r->number,&r->price,&r->day,&r->month,&r->year);

r->title=new char[strlen (buf)+1];

strcpy(r->title, buf);

if(state==7)return 1;

return 0;

}

Приведенный способ достаточно прост, но обладает рядом существенных недостатков.

Во-первых, невозможно прекратить ввод пока не будут введены все поля.

Во-вторых, функции ввода стандартной библиотеки языка Си являются функциями низкого уровня, неконтролирующими правильность ввода данных. При несоответствии вводимых данных заданному формату произойдет аварийное завершение программы. Для правильной организации ввода необходимо выдать сообщение об ошибке ввода конкретного элемента и предоставить пользователю возможность повторить ввод.

Сообщения об ошибках выводятся на экран с использованием различных средств для консольного приложения и приложения с оконным графическим интерфейсом. Поэтому набор функций с сообшениями о различных ошибках в исключительных ситуациях необходимо организовать в виде модуля исключений, интерфейс которго будет одним и тем же, а реализация различна для различных типов приложений.

Пример минимального набора функций из интерфейса модуля исключений приводится ниже

exeptions.h

 

void ExeptionLetters(char* str);

void ExeptionInt(char* str);

void ExeptionFloat(char* str);

void ExeptionRange(double d,double min,double max);

void ExeptionFopen(char* str);

 

Пример реализации для консольного приложения

#include "exeptions.h"

 

void ExeptionInt(char* str)

{printf("\nString %s\t must include letters of digits\n",str);}

 

void ExeptionRange(double d,double min,double max)

{printf("\n Value %f\t must be latter then %f and must be greater then%f\n",d,min,max);}

 

Пример реализации для приложения с оконным графическим интерфейсом

#include "exeptions.h"

 

void ExeptionInt(char* str)

{String* s=new String(str);

s=String::Concate(S"\nString",s,S"\t must include letters of digits\n");

MessageBos::Show(S"ExeptionInt ",s);}

 

void ExeptionRange(double d,double min,double max)

{String* s1=d.ToString();

String* s2=min.ToString();

String* s3=max.ToString();

s1=String::Concate(S"\n Value",s1,S"\t must be latter then ",s2,S"and must be greater then",s3);

MessageBos::Show(S"ExeptionRange",s1);}

 

В связи с тем, что необходимо контролировать ввод каждого конкретного элемента целесообразно производить ввод с использованием промежуточного текстового буфера. После проверки правильности вводимых данных производить преобразование формата и копировать значение в переменные, а в противном случае выдавать сообщение об ошибке.

Даные операции можно реализовать в виде отдельных модулей функций

Модуль функций преобразования:

Заголовочный файл MyConvert.h

int copyto(char** ss,char buf[]);

int copyto(int* i,char buf[]);

int copyto(double* d,char buf[]);

 

Файл реализации MyConvert.cpp

int copyto(char** ss,char buf[])

{ delete [](*ss); //Предполагается, что указатель *ss должен быть правильно //инициализирован, т.е. его значение равно 0, или он был получен с помощью оператора new

*ss =new char[strlen (buf)+1];

strcpy(*ss, buf);

return 1;}

 

int copyto(int* i,char buf[])

{if(IsInt(buf))

*i=atoi(buf);

else return 0;

return 1;}

int copyto(double* i,char buf[]);

Модуль функций для проверки правильности вводимых (validator.h) данных может иметь следующий вид

#pragma once

int IsLetters(char* s);

int IsInt(char* s);

int IsFloat(char* s);

int InRange(double d,double min,double max);

 

Пример реализации

 

#include "validator.h"

#include "exeptions.h"

 

int IsInt(char* s)

{if(s==0)return 0;

for(;*s!='\0' && *s>='0' && *s<='9';s++)

;

if (*s!='\0') {ExeptionInt(s); return 0;}

return 1;}

 

Кроме того, поскольку ввод осуществляется с помощью различных действий, например, для указателей и массивов и в качестве полей могут использоваться другие структуры, то целесообразно разработать отдельные функции ввода - вывода для каждого типа данных и представить их в виде модуля.

Пример минимального набора функций из интерфейса пользовательского модуля ввода - вывода io.h стандартных встроенных типов приводится ниже

#pragma once

typedef FILE* File;

int eof(File fp);

int eof();

void clear(File fp);

void clear();

int input(File fp,char* s);

int input(File fp,char** s);

int input(File fp,int* i);

int input(File fp,double* i);

int input(char* s);

int input(char** s);

int



Поделиться:


Последнее изменение этой страницы: 2016-07-11; просмотров: 816; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 52.15.217.86 (0.014 с.)