Консультация № 185094
07.01.2012, 14:43
277.36 руб.
0 1 1
Здравствуйте, уважаемые эксперты!
Прошу сделать задание из области объектно-ориентированного программирования на С++. Среда - Visual Studio, код прокомментировать.



1. Разработать класс "алфавит" в соответствии со следующим заданием:
Состояние класса -
Алфавит состоит из элементов (знаков) типа char (в алфавите не может быть двух элементов с одинаковыми значениями) и определяется размером (количеством знаков в алфавите) и значениями своих элементов, например: алфавит английских букв (26 элементов: abcdefghijklmnopqrstuvwxyz). Память под алфавит выделяется статически, во время компиляции, и задается массивом фиксированного предельного значения (например, максимальный размер алфавита 100 элементов).
Протокол класса -
Определяет возможности создания и инициализации экземпляров класса и правила использования их (методы класса).
Предусмотреть следующие возможности:
• пустой конструктор для инициализации экземпляров и массивов экземпляров класса по умолчанию;
• создание экземпляров класса с инициализацией размером алфавита (начальный алфавит - заглавные буквы латинского алфавита цифры, строчные буквы латинского алфавита, спецзнаки);
• создание экземпляров класса с инициализацией значениями элементов алфавита как строки ASCII-символов;
• ввод экземпляров класса из входного потока и вывод их значений в выходной поток
(с помощью перегруженных операторов >> и <<);
• объединение двух алфавитов в один (с помощью перегруженного оператора сложения + );
• добавление нового символа в алфавит (с помощью перегруженного оператора += );
• кодирование некоторой строки по заданному алфавиту (алгоритм перекодировки: выбирается очередной символ строки и заменяется символом алфавита, отстоящим от символа строки на n позиций в алфавите, где n задается). Например, если перекодировать строку street в английском алфавите при заданном n = 2, получим: uvtggv. Если требуется закодировать при тех же условиях букву z (символы из конца алфавита), нужно перейти в начало алфавита: b);
• декодирование строки при заданном n (алгоритм, обратный кодированию);
• определение, имеется ли некоторый заданный символ в алфавите.
2. Проектирование класса рекомендуется начать с представления состояния класса, учитывающего заданные операции, а затем реализации конструкторов и перегруженного оператора вывода. Для отладки и исчерпывающего тестирования других методов разработанного класса реализовать диалоговую программу, которая позволяет вводить параметры, отлаживаемых методов.
3. Повторить разработку класса при условии, что память под алфавит необходимой длины выделяется динамически, во время выполнения программы (с помощью оператора new; память задается указателем на char в состоянии класса).
Дополнить интерфейс класса следующими возможностями:
• создание экземпляра класса с его инициализацией другим экземпляром класса (копирующий конструктор);
• переопределение экземпляра класса (с помощью перегруженного оператора присваивания).
4. Написать прикладную программу, использующую разработанный класс.
Примечание: пункты задания, отмеченные (*), являются дополнительными.

Обсуждение

Неизвестный
12.01.2012, 01:36
общий
это ответ
Здравствуйте, Вася Зелепупкин!
Сделала на основании моих ответов 269361, 268954. В комментариях осталось слово "множество" - в Вашем случае это и есть алфавит. Добавила, соответственно, функции кодировки и декодирования, необходимые в Вашем задании. Обратите внимание, данные функции не выделяют память в строке результата.
Вот пример использования класса:
Код:
int _tmain(int argc, _TCHAR* argv[])
{
Set s1 (32), s2 ("abcd");
cout << s1 << endl;
cout << s2;
char a [] = "ABSD", b[5];
s1.Encode (a, b, 10);
s1.Decode (b, a, 10);
cout << a; //здесь строка а должна остаться такой, как была
getch();
return 0;
}


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

Проверено в Visual Studio 2005. Из комментариев всё должно быть ясно, но если будут вопросы, задавайте.

Удачи!

Приложение:
//Статическая память
//Set.h
#pragma once
#include <iostream>
using namespace std;

class Set
{
static const int max_power = 100; //максимальная мощность
char set [max_power]; //массив символов
int power; //мощность
public:
Set () : power(0) {}; //• пустой конструктор для инициализации экземпляров и массивов экземпляров класса по умолчанию;
Set (const Set& s); //конструктор копирования
Set (int p); //• создание экземпляров класса с инициализацией мощностью множества (начальное множество - символы, начиная с символа пробел);
Set (char* str);//• создание экземпляров класса с инициализацией значениями элементов множества как строки символов;
~Set () {}; //деструктор

Set& operator = (const Set& s); //оператор присваивания
Set& operator += (const char e);//• добавление нового элемента в множество (с помощью перегруженного оператора += );
bool In (char e) const;//• определение, имеется ли некоторый заданный элемент в множестве.

bool Encode (char* instr, char* outstr, int n); //кодирование строки
bool Decode (char* instr, char* outstr, int n); //декодирование строки

friend Set operator - (const Set &p1, const Set &p2); //• вычисление разности двух множеств (с помощью перегруженного оператора вычитания -; результирующее множество должно состоять из элементов первого множества без тех, которые есть во втором множестве);
friend Set operator * (const Set &p1, const Set &p2); //• вычисление пересечения двух множеств (с помощью перегруженного оператора умножения *; результирующее множество должно состоять из элементов, имеющихся и в множестве 1, и в множестве 2);
friend Set operator + (const Set &p1, const Set &p2); //• объединение двух множеств (с помощью перегруженного оператора сложения +; результирующее множество должно содержать элементы множества 1 и отличающиеся элементы множества 2);
friend istream & operator >> ( istream & in, Set & p ); // ввод экземпляров класса из входного потока
friend ostream & operator << ( ostream & out, const Set & p ); // вывод в выходной поток

private:
int Find (char c);
};


//Set.cpp

#include "stdafx.h"
#include "Set.h"

Set::Set (const Set& s)
{
power = s.power; //копируем мощность
memcpy (set, s.set, sizeof(char)*power); //копируем данные
}

Set::Set (int p)
{
if (p>max_power) { //если переданная мощность больше максимальной
power = 0; //инициализируем по умолчанию
return;
}
power = p; //сохраняем мощность
char b [] = {65, 48, 97};
char e [] = {90, 57, 255};
int j = 0;
for (int i = 0; i<p; i++) { //заполняем символами
set[i] = b[j]++;
if (b[j]>e[j]) j++;
}
}

Set::Set (char* str)
{
power = 0; //обнуляем мощность
int len = strlen (str); //получаем длину строки
if (len > max_power) return; //если она больше максимальной - выходим
for (int i = 0; i<len; i++) //Заполняем символами из строки
*this+=str[i];
}

Set& Set::operator = (const Set& s)
{ //аналогично конструктору копирования
power = s.power;
memcpy (set, s.set, sizeof(char)*power);
return *this;
}

Set& Set::operator += (const char e)
{
if (power+1>max_power || In(e)) return *this; //если максимальная мощность достигнута или такой элемент уже есть - выходим
set[power] = e; //Добавляем в конец
power++; //увеличиваем мощность
}

bool Set::In (char e) const
{
for (int i = 0; i<power; i++) //ищем символ в массиве
if (set[i] == e) return true; //нашли - возвращаем 1
return false; //не нашли - 0
}

bool Set::Encode (char* instr, char* outstr, int n)
{
int y, l = strlen(instr); //сохраняем длину
for (int i=0; i<l; i++) { //идём по строке
y = Find (instr[i]); //ищем символ в алфавите
if (y<0) return false; //если нет - возвращаем ошибку
if ((y+n)>=power) y = y + n - power; //вычисляем позицию нового символа
else y+=n;
outstr[i] = set[y]; //пишем закодированный символ
}
outstr[l] = '\0'; //обозначаем конец строки
return true;
}

bool Set::Decode (char* instr, char* outstr, int n)
{//всё то же, что в кодировании, только индекс вычисляется наоборот, вычитанием
int y, l = strlen(instr);
for (int i=0; i<l; i++) {
y = Find (instr[i]);
if (y<0) return false;
if ((y-n)<0) y = power + y - n;
else y-=n;
outstr[i] = set[y];
}
outstr[l] = '\0';
return true;
}

int Set::Find (char c)
{//вспомогательная фукнция: вычисляет индекс символа в алфавите
for (int i = 0; i<power; i++) //ищем символ в массиве
if (set[i] == c) return i; //нашли - возвращаем i
return -1; //не нашли - -1
}

Set operator - (const Set &p1, const Set &p2)
{
Set tmp; //буфер
for (int i = 0; i<p1.power; i++) //идём по символам первого множества
if (!p2.In(p1.set[i])) tmp+=p1.set[i]; //если символ первого не содержится во втором, добавляем к результату
return tmp; //возвращаем буфер
}

Set operator * (const Set &p1, const Set &p2)
{
Set tmp;
for (int i = 0; i<p1.power; i++) //если символ первого содержится во втором, добавляем к результату
if (p2.In(p1.set[i])) tmp+=p1.set[i];
return tmp;
}

Set operator + (const Set &p1, const Set &p2)
{
Set tmp;
for (int i = 0; i<p1.power; i++) //просто добавляем к результату все символы первого и второго множеств
tmp+=p1.set[i]; //повторные не добавятся из-за реализации оператора +=
for (int i = 0; i<p2.power; i++)
tmp+=p2.set[i];
return tmp;
}

istream & operator >> ( istream & in, Set & p )
{
cout << "Enter power: ";
in >> p.power;
cout << "Enter chars: ";
for (int i=0; i<p.power; i++)
in >> p.set[i];
return in;
}

ostream & operator << ( ostream & out, const Set & p )
{
out << "{ ";
for (int i = 0; i<p.power-1; i++)
out << p.set[i] << ", ";
out << p.set[p.power-1] << " }";
return out;
}

//Динамическая память
//Set.h
#pragma once
#include <iostream>
using namespace std;

class Set
{
char* set; //массив символов
int power; //мощность
public:
Set () : power(0), set(NULL) {}; //• пустой конструктор для инициализации экземпляров и массивов экземпляров класса по умолчанию;
Set (const Set& s); //конструктор копирования
Set (int p); //• создание экземпляров класса с инициализацией мощностью множества (начальное множество - символы, начиная с символа пробел);
Set (const char* str);//• создание экземпляров класса с инициализацией значениями элементов множества как строки символов;
~Set (); //деструктор

Set& operator = (const Set& s); //оператор присваивания
Set& operator += (const char e);//• добавление нового элемента в множество (с помощью перегруженного оператора += );
bool In (char e) const;//• определение, имеется ли некоторый заданный элемент в множестве.

bool Encode (char* instr, char* outstr, int n); //кодирование строки
bool Decode (char* instr, char* outstr, int n); //декодирование строки

friend Set operator - (const Set &p1, const Set &p2); //• вычисление разности двух множеств (с помощью перегруженного оператора вычитания -; результирующее множество должно состоять из элементов первого множества без тех, которые есть во втором множестве);
friend Set operator * (const Set &p1, const Set &p2); //• вычисление пересечения двух множеств (с помощью перегруженного оператора умножения *; результирующее множество должно состоять из элементов, имеющихся и в множестве 1, и в множестве 2);
friend Set operator + (const Set &p1, const Set &p2); //• объединение двух множеств (с помощью перегруженного оператора сложения +; результирующее множество должно содержать элементы множества 1 и отличающиеся элементы множества 2);
friend istream & operator >> ( istream & in, Set & p ); // ввод экземпляров класса из входного потока
friend ostream & operator << ( ostream & out, const Set & p ); // вывод в выходной поток
private:
void IncSize (); //увеличение размера множества на 1
int Find (char c);
};

//set.cpp
#include "StdAfx.h"
#include "Set.h"


Set::~Set ()
{
if (set!=NULL) delete [] set; //очистка памяти
}

Set::Set (const Set& s)
{
power = s.power; //копируем мощность
set = new char [power]; //выделение памяти
memcpy (set, s.set, sizeof(char)*power); //копируем данные
}

Set::Set (int p)
{
power = p; //сохраняем мощность
set = new char [power];
char b [] = {65, 48, 97};
char e [] = {90, 57, 255};
int j = 0;
for (int i = 0; i<p; i++) { //заполняем символами
set[i] = b[j]++;
if (b[j]>e[j]) j++;
}
}

Set::Set (const char* str)
{
power = 0;
set = NULL;
int len = strlen (str); //получаем длину строки
//set = new char [len];
for (int i = 0; i<len; i++) //Заполняем символами из строки
*this+=str[i];
}

Set& Set::operator = (const Set& s)
{ //аналогично конструктору копирования
power = s.power;
if (set!=NULL) delete [] set;
set = new char [power];
memcpy (set, s.set, sizeof(char)*power);
return *this;
}

void Set::IncSize ()
{
power++; //увеличиваем мощность
if (set==NULL) { //если множество пустое, просто выделяем память
set = new char [power];
return; //и выходим
}
char* s1 = set; //сохраняем старый адрес
set = new char [power]; //выделяем память под новый размер
memcpy (set, s1, sizeof(char)*(power-1)); //копируем элементы
delete [] s1; //очищаем старую память
}

Set& Set::operator += (const char e)
{
if (In(e)) return *this; //если такой элемент уже есть - выходим
IncSize();
set[power-1] = e; //Добавляем в конец
}

bool Set::In (char e) const
{
for (int i = 0; i<power; i++) //ищем символ в массиве
if (set[i] == e) return true; //нашли - возвращаем 1
return false; //не нашли - 0
}

bool Set::Encode (char* instr, char* outstr, int n)
{
int y, l = strlen(instr); //сохраняем длину
for (int i=0; i<l; i++) { //идём по строке
y = Find (instr[i]); //ищем символ в алфавите
if (y<0) return false; //если нет - возвращаем ошибку
if ((y+n)>=power) y = y + n - power; //вычисляем позицию нового символа
else y+=n;
outstr[i] = set[y]; //пишем закодированный символ
}
outstr[l] = '\0'; //обозначаем конец строки
return true;
}

bool Set::Decode (char* instr, char* outstr, int n)
{//всё то же, что в кодировании, только индекс вычисляется наоборот, вычитанием
int y, l = strlen(instr);
for (int i=0; i<l; i++) {
y = Find (instr[i]);
if (y<0) return false;
if ((y-n)<0) y = power + y - n;
else y-=n;
outstr[i] = set[y];
}
outstr[l] = '\0';
return true;
}

int Set::Find (char c)
{//вспомогательная фукнция: вычисляет индекс символа в алфавите
for (int i = 0; i<power; i++) //ищем символ в массиве
if (set[i] == c) return i; //нашли - возвращаем i
return -1; //не нашли - -1
}

Set operator - (const Set &p1, const Set &p2)
{
Set tmp; //буфер
for (int i = 0; i<p1.power; i++) //идём по символам первого множества
if (!p2.In(p1.set[i])) tmp+=p1.set[i]; //если символ первого не содержится во втором, добавляем к результату
return tmp; //возвращаем буфер
}

Set operator * (const Set &p1, const Set &p2)
{
Set tmp;
for (int i = 0; i<p1.power; i++) //если символ первого содержится во втором, добавляем к результату
if (p2.In(p1.set[i])) tmp+=p1.set[i];
return tmp;
}

Set operator + (const Set &p1, const Set &p2)
{
Set tmp;
for (int i = 0; i<p1.power; i++) //просто добавляем к результату все символы первого и второго множеств
tmp+=p1.set[i]; //повторные не добавятся из-за реализации оператора +=
for (int i = 0; i<p2.power; i++)
tmp+=p2.set[i];
return tmp;
}

istream & operator >> ( istream & in, Set & p )
{
cout << "Enter power: ";
in >> p.power;
if (p.set!=NULL) delete [] p.set;
p.set = new char [p.power];
cout << "Enter chars: ";
for (int i=0; i<p.power; i++)
in >> p.set[i];
return in;
}

ostream & operator << ( ostream & out, const Set & p )
{
out << "{ ";
for (int i = 0; i<p.power-1; i++)
out << p.set[i] << ", ";
out << p.set[p.power-1] << " }";
return out;
}

Форма ответа