Форум программистов, компьютерный форум CyberForum.ru

Использование собственного класса строк - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 22, средняя оценка - 4.68
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
15.01.2012, 23:22     Использование собственного класса строк #1
Здравствуйте, уважаемые господа.

Есть реализация собственного класса строк:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
class MyString
{
    private:
        size_t length;
        char *str;
 
    public:
        MyString ();
        MyString (const char *c);
        MyString (const MyString& t);
        ~MyString ();
 
        MyString& operator= (const MyString& t);
        MyString operator+ (const MyString& t) const;
        MyString operator+ (const char *c) const;
        bool operator== (const MyString& t) const;
        bool operator!= (const MyString& t) const;
        void operator+= (const MyString& t);
        char& operator[] (size_t i);
 
        char& at (size_t i);
        void get_input (std::istream& in);
        size_t size () const;
        size_t get_length () const;
 
        friend std::ostream& operator<< (std::ostream& out, const MyString& t);
        friend std::istream& operator>> (std::istream& in, MyString& t);
};
 
MyString::MyString ()
{
    length = 0;
    str = NULL;
}
 
MyString::MyString (const char *c)
{
    length = strlen (c) + 1;
    str = new char[length];
    strcpy (str, c);
    str[length-1] = '\0';
}
 
MyString::MyString (const MyString& t)
{
    length = strlen (t.str) + 1;
    str = new char[length];
    strcpy (str, t.str);
    str[length-1] = '\0';
}
 
MyString::~MyString ()
{
    if (str != NULL)
    {
        delete[] str;
    }
}
 
MyString& MyString::operator= (const MyString& t)
{
    length = strlen (t.str) + 1;
    str = new char[length];
    strcpy (str, t.str);
    str[length-1] = '\0';
 
    return *this;
}
 
MyString MyString::operator+ (const MyString& t) const
{
    char* newStr = new char[strlen (str) + strlen (t.str) + 1];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    newStr[length-1] = '\0';
 
    MyString returnObj (newStr);
    delete[] newStr;
 
    return returnObj;
}
 
bool MyString::operator== (const MyString& t) const
{
    return (strcmp(str, t.str) == 0);
}
 
bool MyString::operator!= (const MyString& t) const
{
    return (strcmp(str, t.str) != 0);
}
 
void MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;
}
 
char& MyString::operator[] (size_t i)
{
    return str[i];
}
 
char& MyString::at (size_t i)
{
    if (i >= 0 && i < length)
    {
        return str[i];
    }
}
 
void MyString::get_input (std::istream& in)
{
    while (true)
    {
        char c = in.get ();
 
        if (c == '\n')
        {
            break;
        }
 
        if (length == 0)
        {
            length = 2;
        }
        else
        {
            ++length;
        }
 
        char* newStr = new char[length];
        if (str != NULL)
        {
            strcpy (newStr, str);
        }
        newStr[length-2] = c;
        newStr[length-1] = '\0';
 
        delete[] str;
 
        str = newStr;
    }
}
 
size_t MyString::size () const
{
    return length;
}
 
size_t MyString::get_length () const
{
    if (length == 0)
    {
        return 0;
    }
    else
    {
        return (length - 1);
    }
}
 
std::ostream& operator<< (std::ostream& out, const MyString& t)
{
    out << t.str;
    return out;
}
 
std::istream& operator>> (std::istream& in, MyString& t)
{
    t.get_input (in);
    return in;
}
Всё ли здесь так, как надо?

Что бы вы предложили добавить сюда и каким образом?

Заранее благодарю за возможные ответы.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
rangerx
1908 / 1517 / 139
Регистрация: 31.05.2009
Сообщений: 2,876
15.01.2012, 23:35     Использование собственного класса строк #2
Для начала добавить константные версии
C++
1
2
3
char& operator[] (size_t i);
//...
char& at (size_t i);
и избавиться от дублирования кода
C++
1
2
3
4
length = strlen (t.str) + 1;
str = new char[length];
strcpy (str, t.str);
str[length-1] = '\0'; // эта строка, кстати говоря, лишняя
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
15.01.2012, 23:35     Использование собственного класса строк #3
поверхностно:
если есть
C++
1
2
                MyString (const char *c);
                MyString (const MyString& t);
то должен быть
C++
1
MyString& operator= (const char* c);
а не только
C++
1
MyString& operator= (const MyString& t);
operator+ , operator== , operator!= - не думаю что должны быть реализованы, как функции-члены

зачем 2 ф-ии, которые логически должны были бы делать одно и то же?
C++
1
2
                size_t size () const;
                size_t get_length () const;
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
15.01.2012, 23:41  [ТС]     Использование собственного класса строк #4
должен быть
MyString& operator= (const char* c);
а не только
MyString& operator= (const MyString& t);
Зачем?

Выражения вида

MyString str;
str = "str";

работают так, как надо.

operator+ , operator== , operator!= - не думаю что должны быть реализованы, как функции-члены
Почему?
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.01.2012, 23:45     Использование собственного класса строк #5
Например, вот поэтому:
C++
1
2
mystring str = "fff";
mystring s = "левый аргумент-не типа mystring" + str;
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
15.01.2012, 23:46     Использование собственного класса строк #6
Цитата Сообщение от YourLastSong Посмотреть сообщение
Зачем?

Выражения вида

MyString str;
str = "str";

работают так, как надо.
чтобы не было лишнего создания временного обьекта


Цитата Сообщение от YourLastSong Посмотреть сообщение
Почему?
потому что им не нужен доступ к закрытым членам класса, а понятие инкапсуляции еще никто не отменял в с++ + пример выше
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
15.01.2012, 23:56     Использование собственного класса строк #7
Начнём с интерфейса:
1. Вы можете присвоить строке другую строку или С-строку, но не можете присвоить ей одиночный символ типа char.
2. Та же история с оператором конкатенации и операторами сравнения. Вы перегрузили оператор сложения для константной С-строки (чего можно было и не делать, ведь есть конструктор-преобразователь, принимающий С-строку), но с одиночными символами опять промашка. К тому же, следует отдельно учесть случай, если символ стоит слева от операции присваивания. То же относится к операторам сравнения.
3. Операторов отношения вообще не наблюдается, что может стать серьёзным недостатком в некоторых случаях.
4. Оператор индексации перегружен только для неконстантного случая, т.е. если строка создана константной, обратиться в конкретному её символу не представляется возможным. То же с методом at.

Теперь по технической стороне вопроса:
1. В конструкторах лучше всё же использовать списки инициализации. Идеология С++ предполагает, что в теле конструктора происходит работа более серьёзная, чем простая инициализация.
2. В деструкторе проверка на NULL лишняя, поскольку оператор delete вполне законно применять к пустому указателю. Кстати говоря, в С++, в отличие от С, предпочтительнее использовать 0, а не NULL (а в новом стандарте, разумеется, надо пользоваться nullptr).
3. Грубейшая ошибка в операторе присваивания. В случае, если строку присваивается самой себе, поведение программы не определено (велика вероятность падения в рантайме). Поясню: мало того, что вы не очищаете старую память (происходит утечка памяти), вы сначала затираете указатель str вновь выделенной памятью (это исключает падение в рантайме, но от этого не легче), а затем делаете strcpy. Если объект слева от знака равно и справа от него один и тот же, то вы сначала в этом объекте выделяете под строку новую память, заполненную мусором, а потом копируете её саму в себя. Как видно, вместо того, чтобы не получить никаких действий в строке str = str;, строка на самом деле будет затёрта, да ещё и память утечёт. Чтобы этого избежать, надо проверять, не совпадают ли адреса присваиваемого объекта и того объекта, которому производится присваивание.
4. В операторе конкатенации производится куча лишних действий в одной безобидной строке: MyString returnObj (newStr); На самом деле куда легче удалить память по указателю str и присвоить ему newStr, в котором уже сформирована результирующая строка. Вернуть достаточно копию *this.
5. Оператор + лучше реализовать через уже написанный operator+=. К чему дублировать код?
6. Метод at в стандартной библиотеке работает следующим образом: если переданный ему индекс не выходит за границу последовательности, возвращается элемент по этому индексу. Иначе кидается исключение std::out_of_range. У вас же во втором случае вообще ничего не происходит, даже никакой фиктивный результат не возвращается и сообщение не выводится. Отсюда и варнинг при компиляции (функция возвращает значение не на всех путях выполнения). Либо кидайте исключение, либо сделайте метод клоном operator[], либо вообще исключите его из класса.
7. Я бы на вашем месте хранил длину строки без учёта завершающего символа. Иначе вам практически везде приходится отнимать единицу. И необходимости в методах size и get_length отпадёт, будете просто возвращать длину. И вообще, к чему пользователю знать реальный размер и длину, когда они всегда отличаются на 1? И в дополнение к этому, я бы при создании пустой строки создавал строку из одного элемента, и инициализировал её '\0'. Это избавит от лишних проверок, поскольку у вас в любом случае будет выделена строка, пусть и нулевой (реально единичной) длины.
8. Метод get_input - это ужас. На каждой итерации выделять память под строку длиной на 1 больше предыдущей - страшно расточительно. Самое простое тут - на каждой итерации выделять строку размером в два раза (или на определённый квант) больше предыдущей итерации. По завершении ввода просто перевыделите строку окончательно длины и скопируете туда символы из предварительной строки большей длины.

Фух, вроде пока всё, что нашёл. Дерзайте.

Добавлено через 1 минуту
Цитата Сообщение от retmas Посмотреть сообщение
потому что им не нужен доступ к закрытым членам класса
Почему?
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
16.01.2012, 00:01     Использование собственного класса строк #8
Цитата Сообщение от silent_1991 Посмотреть сообщение
Почему?
потому что operator+ легко реализуется с помощью operator+=, тем самым используя только открытый интерфейс
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
16.01.2012, 00:02  [ТС]     Использование собственного класса строк #9
Спасибо.

Забыл написать выброс исключения, заметил уже потом.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
16.01.2012, 00:02     Использование собственного класса строк #10
retmas, ага, вот об этом надо говорить отдельно. Я лично напрочь забыл про +=, когда читал ваш комментарий, хотя только что об этом написал в своём
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
16.01.2012, 00:42     Использование собственного класса строк #11
Я вот все хотел спросить, а зачем отдельная функция at? Нельзя разве сделать проверку в перегруженном операторе []?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
16.01.2012, 00:45     Использование собственного класса строк #12
Toshkarik, дополнительная проверка + исключения = потеря производительности. Поэтому оператор индексации ведёт себя так же, как аналогичный оператор для сырых массивов - без всяких проверок. Нужна надёжность - надо использовать at, нужна скорость, привычный синтаксис - оператор индексации.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
16.01.2012, 00:52     Использование собственного класса строк #13
Я так и думал, но ведь исключения обрабатываются только если не пройдена проверка? Неужели эта простая проверка может сильно повлиять на производительность?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
16.01.2012, 00:54     Использование собственного класса строк #14
Toshkarik, если у вас в строке содержится 10000 символов, и вы в цикле проходите по строке, то получаете уже 10000 проверок. Добавим вложенный цикл - получим квадратичную зависимость.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
16.01.2012, 00:54     Использование собственного класса строк #15
Ясно, спасибо.
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
16.01.2012, 18:30  [ТС]     Использование собственного класса строк #16
Спасибо.

Класс нужен лишь для собственного изучения и прекрасно знаю о том, что такие вещи уже давно реализовали другие люди, причём гораздо более умные. Сам лично использую std::string.

Итак, попытался исправить лишь часть недочётов и ошибок:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
class MyString
{
    private:
        size_t length;
        char *str;
 
    public:
        MyString ();
        MyString (const char *c);
        MyString (const MyString& t);
        ~MyString ();
 
        MyString& operator= (const MyString& t);
        MyString& operator= (const char *c);
        MyString operator+ (const MyString& t) const;
        MyString& operator+= (const MyString& t);
        char& operator[] (size_t i);
        const char& operator[] (size_t i) const;
 
        char& at (size_t i);
        const char& at (size_t i) const;
        void get_input (std::istream& in);
        size_t get_length () const;
        void from_c_str (const char *other);
 
        friend std::ostream& operator<< (std::ostream& out, const MyString& t);
        friend std::istream& operator>> (std::istream& in, MyString& t);
        friend bool operator== (const MyString& t, char *c);
        friend bool operator== (const MyString& t, const MyString& t1);
        friend bool operator!= (const MyString& t, char *c);
        friend bool operator!= (const MyString& t, const MyString& t1);
};
 
MyString::MyString ()
{
    length = 1;
    str = '\0';
}
 
MyString::MyString (const char *c)
{
    from_c_str (c);
}
 
MyString::MyString (const MyString& t)
{
    from_c_str (t.str);
}
 
MyString::~MyString ()
{
    delete[] str;
}
 
MyString& MyString::operator= (const MyString& t)
{
    from_c_str (t.str);
 
    return *this;
}
 
MyString& MyString::operator= (const char *c)
{
    from_c_str (c);
 
    return *this;
}
 
MyString MyString::operator+ (const MyString& t) const
{
    return (MyString(str) += t.str);
}
 
bool operator== (const MyString& t, char *c)
{
    return (strcmp(t.str, c) == 0);
}
 
bool operator== (const MyString& t, const MyString& t1)
{
    return (strcmp(t.str, t1.str) == 0);
}
 
bool operator!= (const MyString& t, char *c)
{
    return !(operator== (t, c));
}
 
bool operator!= (const MyString& t, const MyString& t1)
{
    return !(operator== (t, t1.str));
}
 
MyString& MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;
 
    return *this;
}
 
char& MyString::operator[] (size_t i)
{
    return str[i];
}
 
const char& MyString::operator[] (size_t i) const
{
    return str[i];
}
 
char& MyString::at (size_t i)
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::exception ("wrong index");
    }
}
 
const char& MyString::at (size_t i) const
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::exception ("wrong index");
    }
}
 
void MyString::get_input (std::istream& in)
{
    while (true)
    {
        char c = in.get ();
 
        if (c == '\n')
        {
            break;
        }
 
        if (length == 0)
        {
            length = 2;
        }
        else
        {
            ++length;
        }
 
        char* newStr = new char[length];
        if (str != NULL)
        {
            strcpy (newStr, str);
        }
        newStr[length-2] = c;
        newStr[length-1] = '\0';
 
        delete[] str;
 
        str = newStr;
    }
}
 
size_t MyString::get_length () const
{
    return (length - 1);
}
 
void MyString::from_c_str (const char *c)
{
    length = strlen (c) + 1;
    str = new char[length];
    strcpy (str, c);
}
 
std::ostream& operator<< (std::ostream& out, const MyString& t)
{
    out << t.str;
    return out;
}
 
std::istream& operator>> (std::istream& in, MyString& t)
{
    t.get_input (in);
    return in;
}
Есть уже здесь какие-то недочёты, кроме тех, что вы уже назвали?

Извиняюсь, если уже надоел.
rangerx
1908 / 1517 / 139
Регистрация: 31.05.2009
Сообщений: 2,876
16.01.2012, 18:36     Использование собственного класса строк #17
C++
1
2
3
4
5
MyString::MyString ()
{
    length = 1;
    str = '\0';
}
C++
1
2
3
4
5
6
MyString::MyString ()
{
    length = 0;
    str = new char[1];
    *str = '\0';
}
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
16.01.2012, 18:48     Использование собственного класса строк #18
C++
1
2
3
4
5
MyString::MyString ()
{
    length = 1;
    str = '\0';
}
подумайте, что на самом деле означает запись str = '\0'; думаю не то, что вы хотели

и для std::exception нет конструктора, принемающего const char* как аргумент

Добавлено через 4 минуты
добавьте ф-ю аля std::string::c_str
перепишите операторы используя только открытый интерфейс, и надобность в friendах отпадет
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
17.01.2012, 12:40     Использование собственного класса строк #19
YourLastSong, по-прежнему нету операторов отношения.
По-прежнему в функции get_input чудовищно расточительно используются ресурсы.
По-прежнему в операторе присваивания не проверяется присваивание объекта самому себе.

Добавлено через 1 минуту
И в from_c_str не очищается старая память - утечка памяти.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2012, 21:59     Использование собственного класса строк
Еще ссылки по теме:

C++ Использование собственного функтора со связывателями
Создание списка объектов собственного класса (SQL) C++
C++ Std::vector добавить новый элемент собственного класса без использования конструктора копирования

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 21:59  [ТС]     Использование собственного класса строк #20
и для std::exception нет конструктора, принемающего const char* как аргумент
А конструкция вида

throw std::out_of_range ("wrong index");
верна или нет всё же?

перепишите операторы используя только открытый интерфейс, и надобность в friendах отпадет
Какие именно?

Например, как переписать оператор == без доступа к приватным членам класса?

подумайте, что на самом деле означает запись str = '\0'; думаю не то, что вы хотели
Да, разумеется.

По-прежнему в функции get_input чудовищно расточительно используются ресурсы
А как это вообще реализовано, например, в STL?

Сможете написать свой вариант, если не сложно, разумеется?

Попробовал кое-что исправить:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
class MyString
{
    private:
        size_t length;
        char *str;
 
    public:
        MyString ();
        MyString (const char *c);
        MyString (const MyString& t);
        ~MyString ();
 
        MyString& operator= (const MyString& t);
        MyString& operator= (const char *c);
        MyString operator+ (const MyString& t) const;
        MyString& operator+= (const MyString& t);
        char& operator[] (size_t i);
        const char& operator[] (size_t i) const;
 
        char& at (size_t i);
        const char& at (size_t i) const;
        void getline (std::istream& in);
        size_t get_length () const;
        void from_c_str (const char *other);
        char* c_str ();
 
        friend std::ostream& operator<< (std::ostream& out, const MyString& t);
        friend std::istream& operator>> (std::istream& in, MyString& t);
        friend bool operator== (const MyString& t, char *c);
        friend bool operator== (const MyString& t, const MyString& t1);
        friend bool operator!= (const MyString& t, char *c);
        friend bool operator!= (const MyString& t, const MyString& t1);
};
 
MyString::MyString ()
{
    length = 1;
    str = new char[length];
    *str = '\0';
}
 
MyString::MyString (const char *c)
{
    from_c_str (c);
}
 
MyString::MyString (const MyString& t)
{
    from_c_str (t.str);
}
 
MyString::~MyString ()
{
    delete[] str;
}
 
MyString& MyString::operator= (const MyString& t)
{
    if (this == &t)
    {
        return *this;
    }
    from_c_str (t.str);
 
    return *this;
}
 
MyString& MyString::operator= (const char *c)
{
    from_c_str (c);
 
    return *this;
}
 
MyString MyString::operator+ (const MyString& t) const
{
    return (MyString(str) += t.str);
}
 
bool operator== (const MyString& t, char *c)
{
    return (strcmp(t.str, c) == 0);
}
 
bool operator== (const MyString& t, const MyString& t1)
{
    return (strcmp(t.str, t1.str) == 0);
}
 
bool operator!= (const MyString& t, char *c)
{
    return !(operator== (t, c));
}
 
bool operator!= (const MyString& t, const MyString& t1)
{
    return !(operator== (t, t1.str));
}
 
MyString& MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;
 
    return *this;
}
 
char& MyString::operator[] (size_t i)
{
    return str[i];
}
 
const char& MyString::operator[] (size_t i) const
{
    return str[i];
}
 
char& MyString::at (size_t i)
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::out_of_range ("wrong index");
    }
}
 
const char& MyString::at (size_t i) const
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::out_of_range ("wrong index");
    }
}
 
void MyString::getline (std::istream& in)
{
    while (true)
    {
        char c = in.get ();
 
        if (c == '\n')
        {
            break;
        }
 
        if (length == 0)
        {
            length = 2;
        }
        else
        {
            ++length;
        }
 
        char* newStr = new char[length];
        if (str != NULL)
        {
            strcpy (newStr, str);
        }
        newStr[length-2] = c;
        newStr[length-1] = '\0';
 
        delete[] str;
 
        str = newStr;
    }
}
 
size_t MyString::get_length () const
{
    return (length - 1);
}
 
void MyString::from_c_str (const char *c)
{
    length = strlen (c) + 1;
    delete[] str;
    str = new char[length];
    strcpy (str, c);
}
 
char* MyString::c_str ()
{
    return str;
}
 
std::ostream& operator<< (std::ostream& out, const MyString& t)
{
    out << t.str;
    return out;
}
 
std::istream& operator>> (std::istream& in, MyString& t)
{
    t.getline (in);
    return in;
}
Yandex
Объявления
19.01.2012, 21:59     Использование собственного класса строк
Ответ Создать тему
Опции темы

Текущее время: 20:26. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru