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

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

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

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

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

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
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.01.2012, 23:22
Ответы с готовыми решениями:

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

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

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

67
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 22:15
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от YourLastSong Посмотреть сообщение
верна или нет всё же?
Верна. Но у std::exception все же нет по стандарту конструктора, принимающего const char *.

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

Цитата Сообщение от YourLastSong Посмотреть сообщение
А как это вообще реализовано, например, в STL?
Не знаю, лень искать в исходниках. Я вам предлагал уже такой вариант:
Цитата Сообщение от silent_1991 Посмотреть сообщение
Самое простое тут - на каждой итерации выделять строку размером в два раза (или на определённый квант) больше предыдущей итерации. По завершении ввода просто перевыделите строку окончательно длины и скопируете туда символы из предварительной строки большей длины.
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:16
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);
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 22:22
YourLastSong, у вас опять отсутствуют операторы отношения (т.е. операторы <, <=, >, >=).

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

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

константный обхект в операторе + советуют возвращать чтобы не было попыток модифицировать временный объект. мейерс как-то там это аргументировал. я уже не помню деталей.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 22:29
Цитата Сообщение от DU Посмотреть сообщение
будет преобразование или ошибка компиляции
Будет преобразование.

Цитата Сообщение от DU Посмотреть сообщение
это не очень эффективно
Согласен, зато лаконично)))
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:38
ну вот я проверил в студии. мои сомнения подтвердились. если оператор + - метод класса, то преобразования не будет, будет ошибка. если он - свободная ф-ия, то тут да. будет преобразование. но т.к. насоветовали его сделать именно свободной ф-ией, то остается только проблема эффективности
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 22:42
DU, если метод класса - преобразование будет, но только для правого операнда. Ну это естественно, ведь вызов оператора как метода происходит как object.operator+(operand). Поэтому object обязан быть объектом класса. А вот операнд может неявно преобразоваться через конструктор.

Добавлено через 1 минуту
DU, http://liveworkspace.org/code/... f8e3b79d83
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 22:44
ну значит мы друг друга не поняли. я говорил о том, что в текущей реализации нет возможности писать так:
C++
1
"str" + MyString()
const char* в этом случае не будет преобразовываться в MyString , чтобы избавится от ошибки компиляции.
текудая реализация - это оператор + как метод класса а не ф-ия. со свободными ф-иями преобразования будут.
осталось чтобы остальные не запутались
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 22:49
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;
}
0
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 22:50  [ТС]
Она и не нужна, конструктор сыграет роль преобразователя.
Странно, без них программа вылетает при попытке выполнить след. код:

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

binary 'operator +' has too many parameters
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
19.01.2012, 23:10
Цитата Сообщение от YourLastSong Посмотреть сообщение
C++
1
2
3
4
MyString operator+(const MyString& left, const MyString& right)
{
    return MyString(left) += right;
}
Так делать нельзя:
потому что он не должен быть членом класса
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 23:13
YourLastSong, вам уже 10 раз сказали: сделайте оператор + внешней функцией! Вы читаете то, что вам пишут?
0
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 23:14  [ТС]
потому что он не должен быть членом класса
Спасибо.

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

Не получается реализовать 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);
}
К сожалению, он не понимает, какой именно оператор == надо вызывать в данном случае.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 23:17
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);
}
0
19.01.2012, 23:20

Не по теме:

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

1
19.01.2012, 23:21

Не по теме:

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

0
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 112
19.01.2012, 23:24  [ТС]
напишите метод а-ля std::string::c_str. Тогда не понадобится доступ к закрытому полю str.
char* MyString::c_str ()
{
return str;
}
Или надо делать по-другому?
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.01.2012, 23:25
YourLastSong, так.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.01.2012, 23:25

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru