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

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

15.01.2012, 23:22. Показов 6172. Ответов 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru