class rusStr
{
char *stroka;
public:
rusStr(char *s = "")
{
stroka=new char;
strcpy(stroka,filter(s));
}
~rusStr() {delete stroka;}
rusStr operator+ (char* s)
{
strcat(stroka, filter(s));
return *this;
}
rusStr operator+ (rusStr str)
{
strcat(stroka, str.stroka);
return *this;
}
char* filter(char* s)
{
char* str;
str=new char;
//фильтруеться и результат записывается в str;
return str;
}
};
(c++) выделение памяти
Код:
вопрос: нужно ли мне самому удалять str, и если да, то ГДЕ? удаление в деструкторе, конструкторе и в любой фу-ции вызывающей filter(); приводит к ошибке!
и еще, при помощи какой функции можно все содержимое текстового файла содрать в char* s; если можно то пожалуйста на примере.
1) В двух местах встретил new char. Ты уверен, что тебе нужно выделить место под ОДИН символ? Определи требуемый размер, затем выдели new char [ТребуемыйРазмер]. Не забудь, что требуется место и под закрывающий нуль. Насчет strcat в операторе "+" тоже замечание - stroka не рассчитана на столько символов, надо довыделять память.
2) Метод char *filter (char *) не использует данных класса - лучше сделать его статическим.
Теперь собственно по вопросу удаления str. Насколько я понял, речь идет о char *str в методе filter. Во-первых, не удаление приводит к ошибке, а кривое выделение (см. выше, пункт 1). Во-вторых, удалять надо сразу, как выделенное место больше не нужно (в данном случае, в конструкторе сразу после вызова filter). В-третьих, я бы сделал так:
Код:
rusStr(char *s = "")
{
stroka=filter(s);
}
{
stroka=filter(s);
}
А код освобождения уже реализован в деструкторе. По деструктору единственное замечание - пиши delete[] stroka
По второму вопросу создавай отдельную тему.
Цитата: Скотт Майерс
...я использую как обьекты String,так и обьекты string,но для разных целей.(Заметьте,что первое название
пишется с большой буквы,а второе с маленькой.)Если мне просто нужно использовать строку,а ее реализация не важна,то я использую тип string,являющийся частью стандартной библиотеки С++.Этого правила
следует придерживаться и вам.Однако зачастую мне необходимо показать,как работает С++; в таких случаях требуется некоторый код реализации.Тогда я использую нестандартный класс String.Как программист, вы должны всегда,когда вам необходим обьект-строка использовать стандартный тип string;время создания своих собственных классов строк,прежде являющегося неотьемлемой частью ритуала посвящения в С++, уже миновало.Тем не менее необходимо разбираться в вопросах.связанных с созданием классов,подобных string. Для этой и только для этой цели удобно использовать класс String.Что же касается простых строк типа char * , то без веских причин нет необходимости в использовании подобных атавизмов.Хорошо реализованный тип string сегодня предпочтительнее типа char * рпрактически с любой точки зрения,в том числе и с соображений эффективности.
пишется с большой буквы,а второе с маленькой.)Если мне просто нужно использовать строку,а ее реализация не важна,то я использую тип string,являющийся частью стандартной библиотеки С++.Этого правила
следует придерживаться и вам.Однако зачастую мне необходимо показать,как работает С++; в таких случаях требуется некоторый код реализации.Тогда я использую нестандартный класс String.Как программист, вы должны всегда,когда вам необходим обьект-строка использовать стандартный тип string;время создания своих собственных классов строк,прежде являющегося неотьемлемой частью ритуала посвящения в С++, уже миновало.Тем не менее необходимо разбираться в вопросах.связанных с созданием классов,подобных string. Для этой и только для этой цели удобно использовать класс String.Что же касается простых строк типа char * , то без веских причин нет необходимости в использовании подобных атавизмов.Хорошо реализованный тип string сегодня предпочтительнее типа char * рпрактически с любой точки зрения,в том числе и с соображений эффективности.
Кроме Скотта Майерса собственный класс строк(в той или иной степени подробности) рассматривается в книгах Бьерна Страуструпа,Герба Саттера,Стэнли Липпмана,Джима Коплиена и других.Где скачать все эти книги - смотри в Полезных ссылках раздела Студентам.Один из многочисленных примеров собственного класса String.
Код:
#include <iostream>
using namespace std;
class String // Объявление строкового класса
{
private:
char* S; // Строка
size_t len; // Длина строки
public:
String(); // Конструктор по умолчанию
String(const char* s); // Перегруженный конструктор
String(const String& s); // Конструктор копирования
~String() { delete [] S; }// Деструктор
// Дружественные функции
// Перегрузка бинарного оператора
// Функция реализует сцепление строк
friend String operator+(const String&, const String&);
// Перегрузка бинарного оператора
// Функция реализует пересечение строк
friend String operator*(const String&, const String&);
// Перегрузка унарного оператора
// Функция реализует поиск уникальных элементов строки
friend String operator!(const String&);
// Перегрузка бинарного оператора
// Функция реализует ввод объектов класса с клавиатуры
friend istream& operator>>(istream&, String&);
// Перегрузка бинарного оператора
// Функция реализует вывод объектов класса на экран
friend ostream& operator<<(ostream&, const String&);
String& operator=(const String&);
// Перегрузка типа
// Функция реализует преобразование объекта класса к типу char*
operator char*() { return S; }
// Функция сортировки
void Sort(String s[], int n);
// Функция возвращает длину строки
size_t GetLen() { return len; }
};
String::String()
{
S = NULL; // начальная инициализация
len = 0;
}
String::String(const char* s)
{
len = strlen(s);
S = new char[len + 1];
// Инициализация строкой, переданной пользователем
strcpy(S, s);
}
String::String(const String& s)
{
len = s.len;
S = new char[len + 1]; // Безопасное копирование
strcpy(S, s.S);
}
void String::Sort(String s[], int n)
{
// Сортировка строк
bool flag = true;
String temp;
for(int j = 1; ; j++)
{
for(int i = 0; i < n - j; i++)
if(strcmp(s, s[i + 1]) > 0)
// Происходит обращение к
// строкам напрямую, благодаря
// неявному вызову функции класса string
// operator char*()
{
temp = s; // Вызов функции operator=(s)
s = s[i + 1]; // Вызов функции operator=(s[i + 1])
s[i + 1] = temp; // Вызов функции operator=(temp)
flag = false;
}
if(flag)
break;
flag = true;
}
}
String operator+(const String &str1, const String &str2)
{ // Функция сцепления строк
String s; // Создание временного объекта
s.len = str1.len + str2.len;// Вычисление новой длины строки
s.S = new char[s.len + 1]; // Выделение памяти под новую строку
strcpy(s.S, str1.S); // Инициализация первой части строки
strcat(s.S, str2.S); // Инициализация второй части строки
return s; // Возврат нового объекта
}
String operator*(const String &str1, const String &str2)
{ // Функция сцепления строк
String s; // Создание временного объекта
s.len = (str1.len > str2.len)? str1.len : str2.len;
// Вычисление новой длины строки
s.S = new char[s.len + 1]; // Выделение памяти под новую строку
size_t s1 = str1.len; // Длина первой строки
size_t s2 = str2.len; // Длина второй строки
int k = 0; // Индекс результирующей строки
for(size_t i = 0; i < s1; i++)
for(size_t j = 0; j < s2; j++)
if(str1.S == str2.S[j])
{
s.S[k] = str1.S;
// Помещаем найденный символ,
k++; // увеличиваем индекс,
break; // выходим из цикла
}
s.S[k] = 0; // Вставляем завершающий символ \0
s.len = strlen(s.S);
if(s.len > 1){
return !s; // Возврат нового объекта
} // Вызов функции operator !(s)
return s;
}
String operator!(const String& str)
{ // Функция нахождения уникальных
// элементов строк
String s;
size_t l = s.len = str.len;
s.S = new char[s.len + 1];
s.S[0] = str.S[0]; // Копирование первого символа
for(size_t n = 1; n < l; n++)
s.S[n] = 0; // Обнуление остальных элементов
int k = 1; // Индекс для новой строки
bool flag = true;
for(size_t i = 1; i < l; i++) // Поиск уникальных элементов
{
for(size_t j = 0; j < l; j++)
if(s.S[j] == 0)
break;
else if(s.S[j] == str.S)
{
flag = false;
break;
}
if(flag)
{
s.S[k] = str.S; // Добавление уникального символа
// в строку
k++; // Увеличение индекса
}
flag = true;
}
s.S[k] = 0;
return s; // Возврат полученной строки
}
istream& operator>>(istream& is, String& str)
{
const int N = 65536;
// Временный массив для многострочного ввода
char temp[N] = {0};
size_t Length = 0, //длина последней введенной строки,
Total = 0; //общая длина ввода;
// ввод продолжается до ввода пустой строки
do
{
// запрашиваем строку
is.getline(temp + Total, N - Total);
// замеряем длину введенной строки
Length = strlen(temp + Total);
// если строка пуста
if(Length == 0)
break;
// увеличиваем общую длину
Total += Length + 1/* 1 - это \n */;
temp[Total - 1] = '\n';
} while(Total < N);
// Убираем последний Enter
temp[Total - 1] = 0;
// вызываем конструктор преобразования и
// перегруженный оператор присваивания
str = temp;
return is;
}
ostream& operator<<(ostream& os, const String& str)
{
os << str.S; // Вывод строки
return os; // Возврат объекта вывода
}
// Функция, реализующая безопасное присваивание
String& String::operator=(const String &str)
{
if(this == &str)
return *this;
if(len != str.len || len == 0)
{
delete [] S; // Удаление старой строки
len = str.len; // Вычисление новой длины строки
S = new char[len + 1]; // Выделение памяти под новую строку
}
strcpy(S, str.S); // Инициализация строки
return *this; // Возврат ссылки на "самого себя"
// Благодаря этому возможно многократное
// присваивание объектов друг другу
// например, string a, b, c; a = b = c;
}
int _tmain(int argc, _TCHAR* argv[])
{
String a, b, c;
cout << "Input the first part of string:\n";
cin >> a;
cout << "Input the second part of string:\n";
cin >> b;
c = a + "\n" + b + "\n";
cout << c; // Вывод результирующей строки
return 0;
}
using namespace std;
class String // Объявление строкового класса
{
private:
char* S; // Строка
size_t len; // Длина строки
public:
String(); // Конструктор по умолчанию
String(const char* s); // Перегруженный конструктор
String(const String& s); // Конструктор копирования
~String() { delete [] S; }// Деструктор
// Дружественные функции
// Перегрузка бинарного оператора
// Функция реализует сцепление строк
friend String operator+(const String&, const String&);
// Перегрузка бинарного оператора
// Функция реализует пересечение строк
friend String operator*(const String&, const String&);
// Перегрузка унарного оператора
// Функция реализует поиск уникальных элементов строки
friend String operator!(const String&);
// Перегрузка бинарного оператора
// Функция реализует ввод объектов класса с клавиатуры
friend istream& operator>>(istream&, String&);
// Перегрузка бинарного оператора
// Функция реализует вывод объектов класса на экран
friend ostream& operator<<(ostream&, const String&);
String& operator=(const String&);
// Перегрузка типа
// Функция реализует преобразование объекта класса к типу char*
operator char*() { return S; }
// Функция сортировки
void Sort(String s[], int n);
// Функция возвращает длину строки
size_t GetLen() { return len; }
};
String::String()
{
S = NULL; // начальная инициализация
len = 0;
}
String::String(const char* s)
{
len = strlen(s);
S = new char[len + 1];
// Инициализация строкой, переданной пользователем
strcpy(S, s);
}
String::String(const String& s)
{
len = s.len;
S = new char[len + 1]; // Безопасное копирование
strcpy(S, s.S);
}
void String::Sort(String s[], int n)
{
// Сортировка строк
bool flag = true;
String temp;
for(int j = 1; ; j++)
{
for(int i = 0; i < n - j; i++)
if(strcmp(s, s[i + 1]) > 0)
// Происходит обращение к
// строкам напрямую, благодаря
// неявному вызову функции класса string
// operator char*()
{
temp = s; // Вызов функции operator=(s)
s = s[i + 1]; // Вызов функции operator=(s[i + 1])
s[i + 1] = temp; // Вызов функции operator=(temp)
flag = false;
}
if(flag)
break;
flag = true;
}
}
String operator+(const String &str1, const String &str2)
{ // Функция сцепления строк
String s; // Создание временного объекта
s.len = str1.len + str2.len;// Вычисление новой длины строки
s.S = new char[s.len + 1]; // Выделение памяти под новую строку
strcpy(s.S, str1.S); // Инициализация первой части строки
strcat(s.S, str2.S); // Инициализация второй части строки
return s; // Возврат нового объекта
}
String operator*(const String &str1, const String &str2)
{ // Функция сцепления строк
String s; // Создание временного объекта
s.len = (str1.len > str2.len)? str1.len : str2.len;
// Вычисление новой длины строки
s.S = new char[s.len + 1]; // Выделение памяти под новую строку
size_t s1 = str1.len; // Длина первой строки
size_t s2 = str2.len; // Длина второй строки
int k = 0; // Индекс результирующей строки
for(size_t i = 0; i < s1; i++)
for(size_t j = 0; j < s2; j++)
if(str1.S == str2.S[j])
{
s.S[k] = str1.S;
// Помещаем найденный символ,
k++; // увеличиваем индекс,
break; // выходим из цикла
}
s.S[k] = 0; // Вставляем завершающий символ \0
s.len = strlen(s.S);
if(s.len > 1){
return !s; // Возврат нового объекта
} // Вызов функции operator !(s)
return s;
}
String operator!(const String& str)
{ // Функция нахождения уникальных
// элементов строк
String s;
size_t l = s.len = str.len;
s.S = new char[s.len + 1];
s.S[0] = str.S[0]; // Копирование первого символа
for(size_t n = 1; n < l; n++)
s.S[n] = 0; // Обнуление остальных элементов
int k = 1; // Индекс для новой строки
bool flag = true;
for(size_t i = 1; i < l; i++) // Поиск уникальных элементов
{
for(size_t j = 0; j < l; j++)
if(s.S[j] == 0)
break;
else if(s.S[j] == str.S)
{
flag = false;
break;
}
if(flag)
{
s.S[k] = str.S; // Добавление уникального символа
// в строку
k++; // Увеличение индекса
}
flag = true;
}
s.S[k] = 0;
return s; // Возврат полученной строки
}
istream& operator>>(istream& is, String& str)
{
const int N = 65536;
// Временный массив для многострочного ввода
char temp[N] = {0};
size_t Length = 0, //длина последней введенной строки,
Total = 0; //общая длина ввода;
// ввод продолжается до ввода пустой строки
do
{
// запрашиваем строку
is.getline(temp + Total, N - Total);
// замеряем длину введенной строки
Length = strlen(temp + Total);
// если строка пуста
if(Length == 0)
break;
// увеличиваем общую длину
Total += Length + 1/* 1 - это \n */;
temp[Total - 1] = '\n';
} while(Total < N);
// Убираем последний Enter
temp[Total - 1] = 0;
// вызываем конструктор преобразования и
// перегруженный оператор присваивания
str = temp;
return is;
}
ostream& operator<<(ostream& os, const String& str)
{
os << str.S; // Вывод строки
return os; // Возврат объекта вывода
}
// Функция, реализующая безопасное присваивание
String& String::operator=(const String &str)
{
if(this == &str)
return *this;
if(len != str.len || len == 0)
{
delete [] S; // Удаление старой строки
len = str.len; // Вычисление новой длины строки
S = new char[len + 1]; // Выделение памяти под новую строку
}
strcpy(S, str.S); // Инициализация строки
return *this; // Возврат ссылки на "самого себя"
// Благодаря этому возможно многократное
// присваивание объектов друг другу
// например, string a, b, c; a = b = c;
}
int _tmain(int argc, _TCHAR* argv[])
{
String a, b, c;
cout << "Input the first part of string:\n";
cin >> a;
cout << "Input the second part of string:\n";
cin >> b;
c = a + "\n" + b + "\n";
cout << c; // Вывод результирующей строки
return 0;
}