Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/25: Рейтинг темы: голосов - 25, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
1

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

15.01.2012, 23:22. Показов 5245. Ответов 67
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, уважаемые господа.

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

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;
}
Всё ли здесь так, как надо?

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

Заранее благодарю за возможные ответы.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.01.2012, 23:22
Ответы с готовыми решениями:

Запись в собственного класса бинарный файл собственного
есть Свой тип данных дробь. Надо реализовать запись и загрузку в\из бинарного файла. #ifndef...

Использование char строк как членов класса
Изначально всё получалось, смог вывести как надо возраст ( int age ) Но застрял на выводе имени (...

Использование собственного функтора со связывателями
Не могу правильно написать функтор, чтобы его можно было использовать с биндом. Вот пример на...

Создание собственного класса
Создать класс для работы со стеком, организованным как связный однонаправленный список. В классе...

67
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
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'; // эта строка, кстати говоря, лишняя
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
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;
0
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!= - не думаю что должны быть реализованы, как функции-члены
Почему?
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
15.01.2012, 23:45 5
Например, вот поэтому:
C++
1
2
mystring str = "fff";
mystring s = "левый аргумент-не типа mystring" + str;
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
15.01.2012, 23:46 6
Цитата Сообщение от YourLastSong Посмотреть сообщение
Зачем?

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

MyString str;
str = "str";

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


Цитата Сообщение от YourLastSong Посмотреть сообщение
Почему?
потому что им не нужен доступ к закрытым членам класса, а понятие инкапсуляции еще никто не отменял в с++ + пример выше
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
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 Посмотреть сообщение
потому что им не нужен доступ к закрытым членам класса
Почему?
2
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
16.01.2012, 00:01 8
Цитата Сообщение от silent_1991 Посмотреть сообщение
Почему?
потому что operator+ легко реализуется с помощью operator+=, тем самым используя только открытый интерфейс
0
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
16.01.2012, 00:02  [ТС] 9
Спасибо.

Забыл написать выброс исключения, заметил уже потом.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
16.01.2012, 00:02 10
retmas, ага, вот об этом надо говорить отдельно. Я лично напрочь забыл про +=, когда читал ваш комментарий, хотя только что об этом написал в своём
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
16.01.2012, 00:42 11
Я вот все хотел спросить, а зачем отдельная функция at? Нельзя разве сделать проверку в перегруженном операторе []?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
16.01.2012, 00:45 12
Toshkarik, дополнительная проверка + исключения = потеря производительности. Поэтому оператор индексации ведёт себя так же, как аналогичный оператор для сырых массивов - без всяких проверок. Нужна надёжность - надо использовать at, нужна скорость, привычный синтаксис - оператор индексации.
1
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
16.01.2012, 00:52 13
Я так и думал, но ведь исключения обрабатываются только если не пройдена проверка? Неужели эта простая проверка может сильно повлиять на производительность?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
16.01.2012, 00:54 14
Toshkarik, если у вас в строке содержится 10000 символов, и вы в цикле проходите по строке, то получаете уже 10000 проверок. Добавим вложенный цикл - получим квадратичную зависимость.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
16.01.2012, 00:54 15
Ясно, спасибо.
0
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;
}
Есть уже здесь какие-то недочёты, кроме тех, что вы уже назвали?

Извиняюсь, если уже надоел.
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
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';
}
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
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ах отпадет
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.01.2012, 12:40 19
YourLastSong, по-прежнему нету операторов отношения.
По-прежнему в функции get_input чудовищно расточительно используются ресурсы.
По-прежнему в операторе присваивания не проверяется присваивание объекта самому себе.

Добавлено через 1 минуту
И в from_c_str не очищается старая память - утечка памяти.
0
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;
}
0
19.01.2012, 21:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.01.2012, 21:59
Помогаю со студенческими работами здесь

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

Ввод и вывод строки собственного класса
Добрый вечер. Пишу свой класс строк, беда в том, что во вводе что-то, видимо, не так..В общем,...

Создание списка объектов собственного класса (SQL)
очень нужно! объясните, пожалуйста, доходчиво, а лучше с примером, как создать список из объектов...

Увеличение размера массива из элементов собственного класса
Добрый день, столкнулся с проблемой, у меня есть собственный класс myClass{ myClass(){ ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru