Форум программистов, компьютерный форум 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;
}
Всё ли здесь так, как надо?

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

Заранее благодарю за возможные ответы.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:15     Использование собственного класса строк #21
Цитата Сообщение от YourLastSong Посмотреть сообщение
верна или нет всё же?
Верна. Но у std::exception все же нет по стандарту конструктора, принимающего const char *.

Цитата Сообщение от YourLastSong Посмотреть сообщение
как переписать оператор == без доступа к приватным членам класса
У вас есть открытый оператор индексации. Намёк ясен?

Цитата Сообщение от YourLastSong Посмотреть сообщение
А как это вообще реализовано, например, в STL?
Не знаю, лень искать в исходниках. Я вам предлагал уже такой вариант:
Цитата Сообщение от silent_1991 Посмотреть сообщение
Самое простое тут - на каждой итерации выделять строку размером в два раза (или на определённый квант) больше предыдущей итерации. По завершении ввода просто перевыделите строку окончательно длины и скопируете туда символы из предварительной строки большей длины.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:16     Использование собственного класса строк #22
C++
1
2
3
// это лучше сделать в виде ф-ии френда. чтобы можно было добавить оператор +,
// у которого первым идет const char*. Еще советуют возвращать константный объект.
MyString operator+ (const MyString& t) const;
C++
1
2
3
4
5
6
// нет версий, где первый идет const char*
// передаваемый указатель на чар должен быть константным.
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);

У стандартной строки есть ф-ия swap, которая не кидает исключений.

C++
1
2
// лучше возвращать ссылку на строку
void operator+= (const MyString& t);
C++
1
2
3
// в приватную часть класса. хотя если реализовать ф-ию своп, в этом ф-ии не будет нужды. копипаста тоже не будет.
// оператор = можно будет заимплементить созданием временного объекта с const char* и засвопить this  с временным объектом.
void from_c_str (const char *other);
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:22     Использование собственного класса строк #23
YourLastSong, у вас опять отсутствуют операторы отношения (т.е. операторы <, <=, >, >=).

Добавлено через 3 минуты
Цитата Сообщение от DU Посмотреть сообщение
это лучше сделать в виде ф-ии френда
Нет, это лучше сделать в виде глобальной функции-не друга. Потому как есть оператор +=, через который можно реализовать оператор +, не нарушая инкапсуляции.
Цитата Сообщение от DU Посмотреть сообщение
Еще советуют возвращать константный объект
Зачем? Ведь здесь попытка повторить std::string. А в нём оператор конкатенации возвращает неконстантный объект.
Цитата Сообщение от DU Посмотреть сообщение
// нет версий, где первый идет const char*
Она и не нужна, конструктор сыграет роль преобразователя.
Цитата Сообщение от DU Посмотреть сообщение
// лишнее. есть оператор =
Метод std::string::assign как-то лишним никто не называл.
Цитата Сообщение от DU Посмотреть сообщение
// лучше возвращать ссылку на строку
Лучше - это ещё мягко сказано...
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:28     Использование собственного класса строк #24
Зачем? Ведь здесь попытка повторить std::string. А в нём оператор конкатенации возвращает неконстантный объект.
Сообщение от DU
// нет версий, где первый идет const char*
не уверен, будет преобразование или ошибка компиляции. но даже если и будет, это не очень эффективно. выделение памяти все таки в недрах конструктора. для классов общего пользования это играет не последнюю роль.

на счет оператора + - это да. с френдом я погорячился. имплементится за счет публичного operator +=

константный обхект в операторе + советуют возвращать чтобы не было попыток модифицировать временный объект. мейерс как-то там это аргументировал. я уже не помню деталей.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:29     Использование собственного класса строк #25
Цитата Сообщение от DU Посмотреть сообщение
будет преобразование или ошибка компиляции
Будет преобразование.

Цитата Сообщение от DU Посмотреть сообщение
это не очень эффективно
Согласен, зато лаконично)))
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:38     Использование собственного класса строк #26
ну вот я проверил в студии. мои сомнения подтвердились. если оператор + - метод класса, то преобразования не будет, будет ошибка. если он - свободная ф-ия, то тут да. будет преобразование. но т.к. насоветовали его сделать именно свободной ф-ией, то остается только проблема эффективности
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:42     Использование собственного класса строк #27
DU, если метод класса - преобразование будет, но только для правого операнда. Ну это естественно, ведь вызов оператора как метода происходит как object.operator+(operand). Поэтому object обязан быть объектом класса. А вот операнд может неявно преобразоваться через конструктор.

Добавлено через 1 минуту
DU, http://liveworkspace.org/code/9ff20e...772df8e3b79d83
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:44     Использование собственного класса строк #28
ну значит мы друг друга не поняли. я говорил о том, что в текущей реализации нет возможности писать так:
C++
1
"str" + MyString()
const char* в этом случае не будет преобразовываться в MyString , чтобы избавится от ошибки компиляции.
текудая реализация - это оператор + как метод класса а не ф-ия. со свободными ф-иями преобразования будут.
осталось чтобы остальные не запутались
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:49     Использование собственного класса строк #29
DU, потому я и предлагаю реализовывать все операторы без присваивания как внешние функции, посредством тех же операторов с присваиванием. Т.е. operator+ реализовать как внешнюю функцию, принимающую два операнда типа MyString, через operator+=, реализованный, разумеется, как метод. Это логично. Потому что у operator+= слева обязан стоять объект MyString, а справа может стоять как MyString (напрямую принимается оператором), так и const char * (преобразовывается в MyString конструктором). А operator+ реализовать не составит никакого труда на основе operator+=:
C++
1
2
3
4
MyString operator+(const MyString& left, const MyString& right)
{
    return MyString(left) += right;
}
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 22:50  [ТС]     Использование собственного класса строк #30
Она и не нужна, конструктор сыграет роль преобразователя.
Странно, без них программа вылетает при попытке выполнить след. код:

C++
1
2
3
4
5
if ("str" == str)
    std::cout << "aaaaa";
 
if ("s" != str)
    std::cout << "aaaaa";
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 22:51     Использование собственного класса строк #31
YourLastSong, что значит "вылетает"? Если вылетает, значит скомпилировалась, и значит, что с точки зрения компилятора всё верно. Если программа падает - смотрите в свой алгоритм.
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 23:08  [ТС]     Использование собственного класса строк #32
C++
1
2
3
4
MyString operator+(const MyString& left, const MyString& right)
{
    return MyString(left) += right;
}
Так делать нельзя:

binary 'operator +' has too many parameters
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 23:10     Использование собственного класса строк #33
Цитата Сообщение от YourLastSong Посмотреть сообщение
C++
1
2
3
4
MyString operator+(const MyString& left, const MyString& right)
{
    return MyString(left) += right;
}
Так делать нельзя:
потому что он не должен быть членом класса
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 23:13     Использование собственного класса строк #34
YourLastSong, вам уже 10 раз сказали: сделайте оператор + внешней функцией! Вы читаете то, что вам пишут?
YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 23:14  [ТС]     Использование собственного класса строк #35
потому что он не должен быть членом класса
Спасибо.

У вас есть открытый оператор индексации
Проверять каждый элемент отдельно?

Не получается реализовать bool operator!= (const char *c, const MyString& t).

C++
1
2
3
4
bool operator!= (const char *c, const MyString& t)
{
    return (strcmp (c, t.str) != 0);
}
К сожалению, он не понимает, какой именно оператор == надо вызывать в данном случае.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 23:17     Использование собственного класса строк #36
YourLastSong, напишите метод а-ля std::string::c_str. Тогда не понадобится доступ к закрытому полю str.

Добавлено через 42 секунды
Цитата Сообщение от YourLastSong Посмотреть сообщение
он не понимает, какой именно оператор == надо вызывать
Ошибка какая?

Добавлено через 54 секунды
YourLastSong, а вообще, оператор != реализуется через уже написанный operator== так:
C++
1
2
3
4
bool operator!=(const Foo& left, const Foo& right)
{
    return !(left == right);
}
retmas
19.01.2012, 23:20
  #37

Не по теме:

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

silent_1991
19.01.2012, 23:21
  #38

Не по теме:

retmas, полностью согласен, в сообщении 34 последняя моя фраза подтверждает моё согласие

YourLastSong
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 23:24  [ТС]     Использование собственного класса строк #39
напишите метод а-ля std::string::c_str. Тогда не понадобится доступ к закрытому полю str.
char* MyString::c_str ()
{
return str;
}
Или надо делать по-другому?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2012, 23:25     Использование собственного класса строк
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.01.2012, 23:25     Использование собственного класса строк #40
YourLastSong, так.
Yandex
Объявления
19.01.2012, 23:25     Использование собственного класса строк
Ответ Создать тему
Опции темы

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