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

Свой класс string, нужна помощь с перегрузкой операторов

15.01.2024, 17:03. Показов 5840. Ответов 99

Студворк — интернет-сервис помощи студентам
Доброго времени суток.
Создал свой класс string. Цель создания своего класса строк - это скорость работы со строками и второе в образовательных целях. Если реализация получится удачной сделаю библиотеку для личного использования. Сейчас реализованы строки типа char потом добавлю wchar_t. new и delete решил не использовать, так как использую простой тип char. Вроде утечек памяти нет, а работать в теории должно быстрее. Прошу просмотреть код и дать рекомендации по оптимизации или указать на ошибки в коде, буду очень признателен. У меня возник вопрос с перегрузкой операторов, не понимаю как их сделать правильно, представленная реализация вроде работает правильно. Подскажите как правильно перегрузить [], +=, =, +. За ранее благодарю за ответы.

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
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <malloc.h>
 
namespace str
{ 
struct string
{
private:
#pragma region ========================== Variable ==============================
    typedef struct 
    { 
        char *p_str; 
        size_t length;
    }stringA;
 
    stringA str{};
    const type_info& ti_c = typeid(const_cast<const char * >(str.p_str));
 
#pragma endregion 
 
#pragma region ========================== Private Function ==============================
_inline void clr()
{
    if(str.p_str)           free(str.p_str);    
    str.p_str = nullptr;    str.length = 0U;  
}
//------------------------------------------------------------------
_inline bool __type_c(const type_info& ti){return ti_c == ti;}
 
#pragma endregion 
 
 
public:
 
#pragma region ==================================== Constructor ======================================
/* Конструктор однобайтовые символы */
string(const char *p_str)
{   
    clr();
 
   // if(p_str){
        if((str.length = strnlen_s(p_str, SIZE_MAX) ) > 0U)
        { 
            if(str.p_str  = static_cast<char *>(malloc(sizeof(char) * (str.length + 1) ) ) ) 
            {
                strncpy_s(str.p_str, str.length + 1, p_str, _TRUNCATE); 
                str.p_str[str.length] = '\0'; 
                
            }
        }else{  str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) );}
                
   // }
}
//------------------------------------------------------------------
 
/* Конструктор по умолчанию */
explicit string(){     
    clr();
    str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) ); 
}
 
//------------------------------------------------------------------
/* Конструктор копирования */
string(const string& s) 
{
   // if(s.c_str() == ""){  str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) );}else{
 
    clr();
 
    if ((str.length = strnlen_s(s.c_str(), SIZE_MAX)) > 0U) {
        if ((str.p_str = static_cast<char *>    (malloc(sizeof(char) * (str.length + 1) ) ) ) != nullptr) {
    
                strncpy_s(str.p_str, str.length + 1, s.c_str(), _TRUNCATE);
                str.p_str[str.length] = '\0';    
         }
     }
    //}     
}
 
//------------------------------------------------------------------
/* Конструктор перемещения */
string(string &&moved)  noexcept  // ссылка rvalue       
{
    str.p_str = moved.str.p_str;   
    str.length = moved.str.length;
    moved.str.p_str = nullptr;
     
  //  if(str.p_str == nullptr){  str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) ); str.length=0U;}
}
 
//------------------------------------------------------------------
~string(){  clr();  }
 
#pragma endregion
 
#pragma region ====================================== Class Members =======================================
//------------------------------------------------------------------
_inline size_t length() const { return str.length ; }
 
//------------------------------------------------------------------
_inline size_t string_size() const  {   
       return (str.p_str == nullptr) ? 0U : ((str.length +  1) * sizeof(char));    
}
 
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти */
void add(const char *p_str_in)
{   
    size_t l = 0U;
   // if(str.p_str == nullptr) return;    
   
    if ((l = strnlen_s(p_str_in, SIZE_MAX)) != 0U) {
        if ((str.p_str = static_cast<char *> (realloc(str.p_str, (str.length + l + 1) * sizeof(char) ) ) ) != nullptr) {
            
            if(!strcat_s(str.p_str, str.length + l + 1, p_str_in)) str.length += l;
            str.p_str[str.length] = '\0';
        }//else{  str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) ); str.length=0U;}
    }
}
 
//------------------------------------------------------------------
_inline const char* c_str() const {
    return ((str.p_str != nullptr) ? str.p_str : const_cast< char * >(""));
}
 
//------------------------------------------------------------------
/* Вывести символ в строке по индексу от нуля до str.length - 1 */
_inline char ch_at(size_t index) const  {
        return (/*(str.p_str != nullptr) && */(index < str.length)) ? str.p_str[index] : '\0';
}
 
//------------------------------------------------------------------
/* Заменить символ встроке по индексу от нуля до str.length - 1 */
_inline void ch_set_at(size_t index, char ch)   {
            if(/*(str.p_str != nullptr) && */(index < str.length))  str.p_str[index] = ch;
}
//------------------------------------------------------------------
_inline void clear(){ str.p_str   = static_cast<char *>       (calloc(1, sizeof(char) ) ); str.length = 0U;}
 
 
#pragma endregion
 
#pragma region ====================================== Operator Reload ============================================
//------------------------------------------------------------------
 string& operator +=(string const &s )  {      
            this->add(const_cast<char *>(s.c_str()));
            return  *this;
}
 
//------------------------------------------------------------------
  string& operator +=(char *s )    {      
        this->add(static_cast<char *>(s));  
        return  *this;
}
 
//------------------------------------------------------------------
const auto& operator = (const string& s)
{      
   // if (s.c_str() == "")return this;
    clr();
    if ((str.length = strnlen_s(s.c_str(), SIZE_MAX)) != 0U) {
        if ((str.p_str = static_cast<char *>(malloc(sizeof(char) * (str.length + 1) ) ) ) != nullptr) {
    
                strncpy_s(str.p_str, str.length + 1, s.c_str(), _TRUNCATE);
                str.p_str[str.length] = '\0'; 
         }
     }                  
return this;
 
}
 
#pragma endregion
 
//------------------------------------------------------------------ 
 friend std::ostream &operator <<(std::ostream &ostr, string const &point) { ostr << point.c_str(); return ostr; }
 
/* Конец string  */
};
 
//------------------------------------------------------------------
const string operator + (const string &L, const string &R){ return string(L) += R;}    
 
/* Конец области str:: */
};
 
//
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.01.2024, 17:03
Ответы с готовыми решениями:

Класс "Массив дробных чисел" с перегрузкой операторов
Создание консольной программы реализующей перегрузку функции Помогите пожалуйста сделать лабу! Создать проект консольной программы. ...

Класс "Длинные числа" с перегрузкой операторов
только-только начал изучение классов, задание написать класс длинных чисел с перегрузкой операторов если честно, еще очень смутно...

Создать класс "деньги" с перегрузкой операторов
Создать класс деньги поля- гривны, копейки 2 конструктора перегрузить операторы: деньги+деньги деньги-деньги деньги*int ...

99
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
18.01.2024, 21:06  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Signum7, что-то наподобие этого хотели?
C++
1
2
3
4
5
6
7
8
9
10
11
template <class T = char> 
T* custom_memset(T* destination, unsigned char val, size_t size = 1) 
{
    unsigned char* dest = reinterpret_cast<unsigned char*>(destination);
    size *= sizeof(T);
    while(size-- > 0) 
    {
       *dest++ = val;
    }
    return destination;
}
* __cdecl - не нужен. Читайте про соглашения о вызовах;
* unsigned char, раз уж вы внутри в него кастить собрались, проще сразу получать в параметре;
* отдельная функция каста - не нужна. Даже если вы ее напишете, она будет повторять семантику и поведение встроенного каста, и вызов ее будет точно таким же, только вместо reinterpret_cast будет имя вашей функции, т.е. все это будет избыточно;
* раз мы принимаем T*, значит size может быть размером последовательности этих T, поэтому, раз уж вы работаете с байтами, нужно будет домножить на sizeof(T);
* эта функция имеет смысл только для самообразования, потому что ей никогда не обогнать стандартный memset во многих кейсах, потому что стандартный memset - это не только функция, но и intrinsic компилятора.
О благодарю реализация оказалась проще чем я думал
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
19.01.2024, 17:33  [ТС]
Подскажите как правильно сделать проверку char или wchar_t правильно. В качестве типа использовать только эти типы.
Что-то типа такого:
C++
1
2
3
4
5
template<class T = char> 
class string
***
assert(bad_type(T) != nullptr); 
***
0
Заблокирован
19.01.2024, 18:09
Signum7, static_assert плюс is_same
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
19.01.2024, 19:24  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Signum7, static_assert плюс is_same
Благодарю сделал так:
C++
1
2
3
4
5
6
#include <type_traits>
template <class T = char> 
void foo()
{
    static_assert( (std::is_same_v<T,char> ? true : std::is_same_v<T,wchar_t> ? true : false )," Err Type ");
}
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
19.01.2024, 19:33
Цитата Сообщение от Signum7 Посмотреть сообщение
(std::is_same_v<T,char> ? true : std::is_same_v<T,wchar_t> ? true : false)
Зачем такое городить?
C++
1
static_assert(std::is_same_v<T,char> || std::is_same_v<T,wchar_t>, " Err Type ");
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
19.01.2024, 19:38  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
static_assert(std::is_same_v<T,char> || std::is_same_v<T,wchar_t>, " Err Type ");
А я так сначала и сделал, но мне показалось как-то не интересно и переделал на тот вариант который выставил на форум
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
19.01.2024, 19:52
Signum7, через задницу и само без усилий получится, а специально лучше так не делать
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
20.01.2024, 02:15
Цитата Сообщение от Signum7 Посмотреть сообщение
C++
1
2
3
4
5
template <class T = char> 
void foo()
{
    static_assert( (std::is_same_v<T,char> ? true : std::is_same_v<T,wchar_t> ? true : false )," Err Type ");
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <type_traits>
 
template <class T = char> 
void foo() requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
}
 
int main() 
{
  foo();
  foo<>(); 
  foo<char>();
  foo<wchar_t>();
  foo<int>(); // ERROR
}
2
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
20.01.2024, 18:36  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
чем лучше static_assert есть ли смысл включать с++20 для моего проекта?
0
Заблокирован
20.01.2024, 20:37
Signum7, static_assert доступен с C++11.
C++ - статически типизированный ЯП. То есть, ошибка будет обнаружена на этапе компиляции, с assert , только в режиме выполнения и только в отладочном режиме, в релизе его не будет.
Ну а requiers, да с 20, приведен как возможность современног C++.
Вопрос нужен ли вам вообще С++?
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
20.01.2024, 20:44  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Signum7, static_assert доступен с C++11.
C++ - статически типизированный ЯП. То есть, ошибка будет обнаружена на этапе компиляции, с assert , только в режиме выполнения и только в отладочном режиме, в релизе его не будет.
Ну а requiers, да с 20, приведен как возможность современног C++.
Вопрос нужен ли вам вообще С++?
Тогда посоветуйте мне изучаю с++, стоит ли тогда его изучать с упором на с++20 или для начинающих не стоит на него пока переходить а использовать возможности старых версий 14++ 17++
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
20.01.2024, 20:49
Цитата Сообщение от Signum7 Посмотреть сообщение
чем лучше static_assert есть ли смысл включать с++20 для моего проекта?
Это разные вещи. static_assert - это пост-проверка. То есть ваша шаблонная функция всегда существует, но если вы вызовете ее неправильно, то произойдет ошибка.

requires - это constraint. Это пре-проверка, которая принимается во внимание в процессе overload resolution. В результате для неправильного набора шаблонных параметров такой функции не будет существовать вообще (или может правильнее сказать, что для неправильного набора шаблонных параметров она будет невидимой).

Constraints - развитие идеи SFINAE и в частности std::enable_if. То есть того же самого вы могли добиться и в С++11, используя std::enable_if вместо requires

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <type_traits>
 
template <class T = char> 
typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, wchar_t>::value>::type foo()
{
}
 
int main() 
{
  foo();
  foo<>(); 
  foo<char>();
  foo<wchar_t>();
  foo<int>(); // ERROR
}
То есть C++20 тут совсем не обязателен. А дальше уже решайте, что вам больше нравится: пре-проверка или пост-проверка.
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
20.01.2024, 21:42  [ТС]
Сделал такие функции для своего класса вместо перегрузки strcpy_s wcscpy_s решил сделать свои шаблонные. не хочу UB b прочую гадость посмотрите пожалуйста.

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
//------------------------------------------------------------------
/* Длина строки (количество символов без нуля) */
template <class T = char> 
size_t custom_strnlen(const T* str ) requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)/* тут проверил requires*/
{  
   assert(str != nullptr);    
   size_t length = 0;
   while (*str++ != 0) length++;
 
   return length;
};
 
//------------------------------------------------------------------
/*  */
template <class T = char> /* Функция копирует указанное число символов из строки с завершающим нулем,  mem - размер памяти */
void  custom_strncpy_s(T* destination, const T* strc, size_t size = 0U,  size_t mem = SIZE_MAX)
{
 // size_t str_length = size > 0 ? size  : 1U;
 
  assert((destination != nullptr) || (strc != nullptr));
 
  if (size < mem) {
        while (size-- && (*destination++ = *strc++));
        *destination = 0;
    }
}
//------------------------------------------------------------------
template <class T = char>  /* Функция склеивает указанное число символов из строки с завершающим нулем,  mem - размер памяти */
void custom_strncat_s(T* destination, const T* strc, size_t size = 0U , size_t mem = SIZE_MAX)
{
    assert((destination != nullptr) || (strc != nullptr));  
    if (!(size < mem))return ;
 
    size_t str_length = custom_strnlen<T>(destination); 
 
    size_t tmp = ((tmp = size + str_length) < mem) ? size : mem - str_length ;
 
    T* ptr = destination + str_length;
    
    while (*strc != 0 && tmp-- )
    {
        *ptr++ = *strc++;
    }*ptr = 0; 
}
 
template <class T = char>  
void custom_strncat_s(T* destination, size_t size1  ,const T* strc, size_t size2 = 0U , size_t mem = SIZE_MAX)
{
    assert((destination != nullptr) || (strc != nullptr));  
    if (!((size1 + size2) < mem))return ;
 
    T* ptr = destination + size1;
    
    while (*strc != 0 && size2-- )
    {
        *ptr++ = *strc++;
    }*ptr = 0; 
}
 
 
//------------------------------------------------------------------
template <class T = char> 
int custom_cscmp(const T* str1, const T* str2) 
{
    assert((str1 != nullptr) || (str2 != nullptr));
    while ( *str1 && *str2 && *str1 == *str2 ) ++str1, ++str2;       
    return *str1 - *str2;
}
Добавлено через 15 минут
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
То есть C++20 тут совсем не обязателен. А дальше уже решайте, что вам больше нравится: пре-проверка или пост-проверка.
для случая str != nullptr, что лучше?


Добавил еще такую функцию
C++
1
2
3
4
5
6
7
8
9
template <class T = char> 
inline static void str_cat(T* destination, size_t size1  , const T* strc, size_t size2){
    T* ptr = destination + size1;
    
    while (*strc != 0 && size2-- )
    {
        *ptr++ = *strc++;
    }*ptr = 0; 
}
Это чтобы не дублировать код
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
20.01.2024, 23:02
Цитата Сообщение от Signum7 Посмотреть сообщение
для случая str != nullptr, что лучше?
Не совсем понимаю, при чем здесь str != nullptr. str != nullptr - это, естественно, проверка именно времени выполнения, которая никакого отношения ни к каким static_assert/requires/stf::enable_if не имеет вообще.
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
21.01.2024, 01:50  [ТС]
То что на данный момент
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
/* Класс string только для строк  char или wchar_t */
template<class T = char> 
class string 
{static_assert(std::is_same_v<T,char> || std::is_same_v<T,wchar_t>, " Err Type ");
private:
 
//------------------------------------------------------------------
private:
 
        size_t  leng{0U};           /* Количество символов в строке */
        size_t  size_str{0U};       /* Размер выделенной памяти для строки */     
        T       *p_str{nullptr};    /* Строка */
 
//------------------------------------------------------------------
void realloc_foo(size_t &len)
{
        T *p_str_t = nullptr; if (len == leng)return;        
        
        if ((p_str_t = static_cast<T *> (realloc(p_str, (leng + len + 1) * sizeof(T)))) != nullptr) p_str = p_str_t;
             p_str_t = nullptr;             
        
}
 
//------------------------------------------------------------------
void malloc_foo(size_t &len)
{   
        T *p_str_t = nullptr;
        if ((p_str_t = static_cast<T *>(malloc(sizeof(T) * (len + 1) ) ) ) != nullptr) p_str = p_str_t;
             p_str_t = nullptr;                   
}
 
//------------------------------------------------------------------
void construct(const T *pstr) {
          
        assert(pstr != nullptr);
        if((leng = custom_strnlen<T>(pstr) ) > 0U) { malloc_foo(leng); /*assert(p_str != nullptr);*/
                   custom_strncpy_s<T>(p_str,pstr,leng);
        }
}
//------------------------------------------------------------------
public:
 
/* Конструктор символы */
 string(const T *pstr) {
            assert(pstr != nullptr);std::cout << " Конструктор символы " << std::endl; 
            if((leng = custom_strnlen<T>(pstr) ) > 0U) { malloc_foo(leng); /*assert(p_str != nullptr);*/
                    custom_strncpy_s<T>(p_str,pstr,leng);
            }  
 }
 
//------------------------------------------------------------------
 
/* Конструктор по умолчанию */
string() { p_str = static_cast<T *> (calloc(1, sizeof(T) ) ); size_str = 1; }
 
//------------------------------------------------------------------
/* Конструктор копирования */
string(const string& s) {
    std::cout << " Конструктор копирования " << std::endl; 
    construct(s.p_str);
    /* не работает */
    //size_t l = s.leng;malloc_foo(l); /*assert(p_str != nullptr);*/
    //custom_strncpy_s<T>(p_str, s.p_str, l);
}
 
//------------------------------------------------------------------
/* Конструктор перемещения */
string(string &&moved) noexcept 
{  std::cout << " Конструктор перемещения " << std::endl; 
            size_str        = moved.size_str;          
            p_str           = moved.p_str;   
            leng            = moved.leng;
            moved.p_str     = nullptr;
            moved.size_str  = moved.leng = 0U; 
}
 
//------------------------------------------------------------------
~string() noexcept {
            if(p_str != nullptr)    free(p_str);    
            p_str = nullptr;        size_str = leng = 0U;  
}
 
//------------------------------------------------------------------
size_t length() const { return leng ; }
 
//------------------------------------------------------------------
size_t string_size() const  {   
            return (p_str == nullptr) ? 0U : ((leng +  1) * sizeof(T));    
}
 
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти */
 
void add(const T *p_str_in)
{  
    assert(p_str_in != nullptr || p_str != nullptr); size_t l = 0;
   std::cout << " add ch " << std::endl; 
     if ((l = custom_strnlen<T>(p_str_in)) != 0U) { 
            realloc_foo(l); 
            custom_strncat_s<T>(p_str, leng, p_str_in, l); leng += l;          
        }    
}
//------------------------------------------------------------------
void add(const string& s)
{   std::cout << " add string " << std::endl;  
    size_t l = s.leng ; realloc_foo(l); 
    custom_strncat_s<T>(p_str,leng,s.p_str,l); 
}
//------------------------------------------------------------------
const T* c_str() const { return (p_str != nullptr) ? p_str : 0; }
 
//------------------------------------------------------------------
void clear() { }
 
//------------------------------------------------------------------
string &operator += (string const &s )  { add(s); return  *this; }
 
string &operator += (const T *str )     { add(str); return  *this; }
 
//------------------------------------------------------------------
const string &operator = (const string & s) {            
                string tmp(s); swap (*this, tmp); 
                return *this;
}
//------------------------------------------------------------------
string &operator = (string&& moved) noexcept            { swap (*this, moved); return *this; }
 
//------------------------------------------------------------------ 
        string &operator[]  (const size_t index)        { assert(index < leng); return p_str[index]; }
 const   string &operator[] (const size_t index) const  { assert(index < leng); return p_str[index]; }
        string *operator->  ()                          { return this; }
 
//------------------------------------------------------------------ 
 friend std::wostream &operator <<  (std::wostream &ostr,   string<T> const &str)   {ostr << str.c_str(); return ostr;}
 friend std::wistream &operator >> (std::wistream &in,  string<T>           &str)   {}
 
 friend std::ostream &operator << (std::ostream &ostr,  string<T> const &str)       {ostr << str.c_str(); return ostr;}
 friend std::istream &operator >> (std::istream &in,    string<T>           &str)   {}
 
 friend  const string operator + (const string<T> &l, const string<T> &r)                   {return string<T>(l) += r;} 
 //------------------------------------------------------------------ 
 friend void swap (string &l, string &r)
    {
        std::swap (l.p_str ,    r.p_str);
        std::swap (l.leng ,     r.leng);
        std::swap (l.size_str , r.size_str);
    }
 //------------------------------------------------------------------ 
friend bool operator <  (const string &l, const string &r) noexcept {/**/}
 
friend bool operator >  (const string &l, const string &r) noexcept {/**/}
 
friend bool operator == (const string &l, const string &r) noexcept {/**/}
 
 
//------------------------------------------------------------------ 
 
/* Конец string  */
};
0
Покинул чат.
1132 / 727 / 195
Регистрация: 30.03.2021
Сообщений: 2,379
21.01.2024, 02:02
Цитата Сообщение от Signum7 Посмотреть сообщение
string &operator[] 
а разве не Т &operator[] ?
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
21.01.2024, 06:05  [ТС]
Цитата Сообщение от sdf45 Посмотреть сообщение
а разве не Т &operator[] ?
Да вот исправленный кусок
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
//------------------------------------------------------------------ 
         T &operator[]  (const size_t index)        { assert(index < leng); return p_str[index]; }
 const   T &operator[]  (const size_t index) const  { assert(index < leng); return p_str[index]; }
        string *operator->  ()                          { return this; }
 
//------------------------------------------------------------------ 
 friend std::wostream &operator <<  (std::wostream &ostr,   string<T> const &str)   {ostr << str.c_str(); return ostr;}
 friend std::wistream &operator >> (std::wistream &in,  string<T>           &str)   {}
 
 friend std::ostream &operator << (std::ostream &ostr,  string<T> const &str)       {ostr << str.c_str(); return ostr;}
 friend std::istream &operator >> (std::istream &in,    string<T>           &str)   {}
 
 friend  const string operator + (const string<T> &l, const string<T> &r)                   {return string<T>(l) += r;} 
 //------------------------------------------------------------------ 
 friend void swap (string<T> &l, string<T> &r)
    {
        std::swap (l.p_str ,    r.p_str);
        std::swap (l.leng ,     r.leng);
        std::swap (l.size_str , r.size_str);
    }
 //------------------------------------------------------------------ 
friend bool operator <  (const string<T> &l, const string<T> &r) noexcept {/**/}
 
friend bool operator >  (const string<T> &l, const string<T> &r) noexcept {/**/}
 
friend bool operator == (const string<T> &l, const string<T> &r) noexcept {/**/}
 
 
//------------------------------------------------------------------
Добавлено через 3 часа 51 минуту
Вот полностью рабочий класс проверьте пожалуйста, буду признателен. Уже глаза замылились нечего не вижу.

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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#include <iostream>
#include <locale.h>
#include <malloc.h>
#include <type_traits>
#include <cassert>
 
 
namespace str
{
//#define SIZE 10000
 
constexpr   size_t  TRUNCATE = ((size_t)-1);
constexpr   bool STACK_STRING = false ;
#ifndef SIZE
constexpr   size_t SIZE_STRING = 260 ; /* символов */
#else
constexpr   size_t SIZE_STRING = SIZE ;
#if (SIZE < 260)
constexpr   bool STACK_STRING = true ; /* Возможно для маленьких строк сделаю на стеке */
#else
constexpr   bool STACK_STRING = false ;
#endif
#endif
 
//------------------------------------------------------------------
/* Длина строки (количество символов без нуля) */
template <class T = char> 
inline size_t custom_strnlen(const T* str,size_t mem = SIZE_MAX )
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{  
   assert(str != nullptr);    
   size_t length = 0;
   while (*str++ != 0) length++;
 
   return length;
};
 
//------------------------------------------------------------------
/*  */
template <class T = char> /* Функция копирует указанное число символов из строки с завершающим нулем,  mem - размер памяти */
inline void  custom_strncpy_s(T* destination, const T* strc, size_t size = 0U,  size_t mem = SIZE_MAX) 
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
  assert((destination != nullptr) || (strc != nullptr));
 
  if (size < mem) {
        while (size-- && (*destination++ = *strc++));
        *destination = 0;
    }
}
//------------------------------------------------------------------
template <class T = char> 
inline static void str_cat(T* destination, size_t size1  , const T* strc, size_t size2)
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
 
{
    T* ptr = destination + size1;
    
    while (*strc != 0 && size2-- )
    {
        *ptr++ = *strc++;
    }*ptr = 0; 
}
//------------------------------------------------------------------
template <class T = char>  /* Функция склеивает указанное число символов из строки с завершающим нулем,  mem - размер памяти */
inline void custom_strncat_s(T* destination, const T* strc, size_t size = 0U , size_t mem = SIZE_MAX)
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
    assert((destination != nullptr) || (strc != nullptr));  
    if (!(size < mem))return ;
 
    size_t str_length = custom_strnlen<T>(destination); 
 
    size_t tmp = ((tmp = size + str_length) < mem) ? size : mem - str_length ;
    str_cat(destination, str_length, strc, tmp);
}
//------------------------------------------------------------------
template <class T = char>  
inline void custom_strncat_s(T* destination, size_t size1  ,const T* strc, size_t size2 = 0U , size_t mem = SIZE_MAX)
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
    assert((destination != nullptr) || (strc != nullptr));  
    if (!((size1 + size2) < mem))return ;
 
    str_cat(destination, size1, strc, size2);
}
 
//------------------------------------------------------------------
template <class T = char> 
inline int custom_cscmp(const T* str1, const T* str2) 
    requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
    assert((str1 != nullptr) || (str2 != nullptr));
    while ( *str1 && *str2 && *str1 == *str2 ) ++str1, ++str2;       
    return *str1 - *str2;
}
 
//===================================================================================================================
/* Класс string только для строк  char или wchar_t */
template<class T = char> 
class string 
{static_assert(std::is_same_v<T,char> || std::is_same_v<T,wchar_t>, " Err Type ");
private:
 
//------------------------------------------------------------------
private:
 
        size_t  leng{0U};           /* Количество символов в строке */
        size_t  size_str{0U};       /* Размер выделенной памяти для строки */     
        T       *p_str{nullptr};    /* Строка */
 
//------------------------------------------------------------------
void realloc_foo(size_t len)
{
        T *p_str_t = nullptr; if (len + 1 == size_str)return;
 
        if(len < SIZE_STRING) size_str = SIZE_STRING; else size_str = len + 1;
 
        if ((p_str_t = static_cast<T *> (realloc(p_str, (size_str) * sizeof(T)))) != nullptr) p_str = p_str_t;
             p_str_t = nullptr; assert(p_str != nullptr); 
}
 
//------------------------------------------------------------------
void malloc_foo(size_t len)
{   if(len < SIZE_STRING) size_str = SIZE_STRING; else size_str = len + 1;
        T *p_str_t = nullptr;
        if ((p_str_t = static_cast<T *>(malloc(sizeof(T) * (size_str) ) ) ) != nullptr) p_str = p_str_t;
             p_str_t = nullptr; assert(p_str != nullptr);                 
}
 
//------------------------------------------------------------------
public:
 
/* Конструктор символы */
 string(const T *pstr) {
            assert(pstr != nullptr);
            if((leng = custom_strnlen<T>(pstr) ) > 0U) { malloc_foo(leng); 
                    custom_strncpy_s<T>(p_str,pstr,leng, size_str);
            }  
 }
 
//------------------------------------------------------------------
 
/* Конструктор по умолчанию */
string() { 
    size_str =  SIZE_STRING ;
    p_str = static_cast<T *> (calloc(size_str, sizeof(T) ) ); 
; }
 
//------------------------------------------------------------------
/* Конструктор копирования */
string(const string<T>& s) {    
    leng  = s.leng; realloc_foo(leng);
    custom_strncpy_s<T>(p_str, s.p_str, leng, size_str); 
}
 
 
//------------------------------------------------------------------
/* Конструктор перемещения */
string(string<T> &&moved) noexcept 
{  
            size_str        = moved.size_str;          
            p_str           = moved.p_str;   
            leng            = moved.leng;
            moved.p_str     = nullptr;
            moved.size_str  = moved.leng = 0U; 
}
 
//------------------------------------------------------------------
~string() noexcept {
            if(p_str != nullptr)    free(p_str);    
            p_str = nullptr;        size_str = leng = 0U;  
}
 
//------------------------------------------------------------------
size_t length() const { return leng ; }
 
//------------------------------------------------------------------
size_t string_size() const  {   
            return (p_str == nullptr) ? 0U : ((leng +  1) * sizeof(T));    
}
 
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти */
 
void add(const T *p_str_in)
{  
    assert(p_str_in != nullptr || p_str != nullptr); size_t l = 0;   
     if ((l = custom_strnlen<T>(p_str_in)) != 0U) { 
            realloc_foo(leng + l); 
            custom_strncat_s<T>(p_str, leng, p_str_in, l, size_str); leng += l;          
        }    
}
//------------------------------------------------------------------
void add(const string<T>& s)
{     
    size_t l = s.leng ; realloc_foo(leng + l); 
    custom_strncat_s<T>(p_str, leng, s.p_str, l, size_str); leng += l; 
}
//------------------------------------------------------------------
const T* c_str() const { return (p_str != nullptr) ? p_str : 0; }
 
//------------------------------------------------------------------
void clear() { 
    *p_str = (T)'\0'; leng = custom_strnlen<T>(p_str); 
    size_str =  SIZE_STRING ;
    realloc_foo(size_str - 1); }
 
//------------------------------------------------------------------
string<T> &operator += (string<T> const &s )    { add(s); return  *this; }
 
string<T> &operator += (const T *str )      { add(str); return  *this; }
 
//------------------------------------------------------------------
const string<T> &operator = (const string<T> & s) {            
                string<T> tmp(s); swap (*this, tmp); 
                return *this;
}
//------------------------------------------------------------------
string<T> &operator = (string<T>&& moved)   noexcept    { swap (*this, moved); return *this; }
 
//------------------------------------------------------------------ 
            T &operator[]   (const size_t index)        { assert(index < leng); return p_str[index]; }
 const      T &operator[]   (const size_t index) const  { assert(index < leng); return p_str[index]; }
            string<T> *operator->   ()                  { return this; }
 
//------------------------------------------------------------------ 
 friend std::wostream &operator << (std::wostream &ostr,    string<T> const &str)   { ostr << str.c_str(); return ostr;}
 friend std::wistream &operator >> (std::wistream &in,  string<T>           &str)   {}
 
 friend std::ostream &operator << (std::ostream &ostr,  string<T> const &str)       { ostr << str.c_str(); return ostr;}
 friend std::istream &operator >> (std::istream &in,    string<T>           &str)   {}
 
 friend  const string<T> operator + (const string<T> &l, const string<T> &r)        {  return string<T>(l) += r;} 
 //------------------------------------------------------------------ 
 friend void swap (string<T> &l, string<T> &r)
    { 
        std::swap (l.p_str ,    r.p_str);
        std::swap (l.leng ,     r.leng);
        std::swap (l.size_str , r.size_str);
    }
 //------------------------------------------------------------------ 
friend bool operator <  (const string<T> &l, const string<T> &r) noexcept {/**/}
 
friend bool operator >  (const string<T> &l, const string<T> &r) noexcept {/**/}
 
friend bool operator == (const string<T> &l, const string<T> &r) noexcept {/**/}
 
 
//------------------------------------------------------------------ 
#ifdef SIZE
#undef SIZE
#endif
/* Конец string  */
};
 
//------------------------------------------------------------------
/* Конец области str:: */
};
Добавлено через 5 минут
Так я тестировал на вылеты, вроде норм
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 for(size_t i = 0; i< 1000;i++)
 {
        str::string str(L"Привет ");
        str::string st(L" ghbdtn ");
        str::string str1(L" Вася Пупкин ");
        str::string str2(L" Мир !");
        str::string str3 = std::move(st);
 
        str += str2; 
        str = str1  + str + str2  + L" Не Может" + L" Может";
         
        std::wcout << __FUNCTION__<< L" Итоговая строка : \t" << str << L" Length :" << str.length() << std::endl;
        str = str1; str1 += str2;
        std::wcout << __FUNCTION__<< L" Итоговая строка : \t" << str << L" Length :" << str.length() << std::endl; 
        str1 = str; str->clear();
        std::wcout << __FUNCTION__<<L" Итоговая строка : \t" <<str1 << L" Length :" << str1.length() << std::endl; 
 
}
0
Покинул чат.
1132 / 727 / 195
Регистрация: 30.03.2021
Сообщений: 2,379
21.01.2024, 17:56
https://github.com/JeremyDsilva/String
бегло пролистал, по-моему очень похоже на то, что ты пишешь. (но не шаблонах)
там в срр есть оператор >> в самом конце
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
21.01.2024, 21:21  [ТС]
Цитата Сообщение от sdf45 Посмотреть сообщение
https://github.com/JeremyDsilva/String
бегло пролистал, по-моему очень похоже на то, что ты пишешь. (но не шаблонах)
там в срр есть оператор >> в самом конце
ого там классище идею оператора >> посмотрел там, еще вариант конструктора там еще один себе такой же сделаю, передавать строку уже с запрашиваем размером буфера идея интересная.

Добавлено через 1 час 21 минуту
нашел такую конструкцию скажите ее можно использовать? либо есть альтернативы которые можете рекомендовать?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::wstring str2wstr(std::string_view str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), nullptr, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}
std::string wstr2str(const std::wstring& wstr)
{
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0);
    std::string strTo(size_needed, 0);
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0);
    return strTo;
}
Не совсем подходит просит #include <windows.h>
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 133
22.01.2024, 17:05  [ТС]
Свой шаблонный класс string для char wchar_t, оптимизация Продолжение...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.01.2024, 17:05
Помогаю со студенческими работами здесь

Разработать класс "Сотрудник" (с перегрузкой операторов)
задание следующее Разработать класс для хранения информации о сотруднике, включая ФИО, зарплату, должность (определяемую значениями...

Написать класс "Дата" с перегрузкой операторов
Здравствуйте, задание: написать класс Дата с перегрузкой операторов. Вот мой код. Почему-то компилятор выбивает, что в main Data и d1 не...

Создать класс "Полином" с перегрузкой операторов
Помимо функций, указанных в задании, включить в реализацию класса конструкторы всех типов, функции ввода-вывода. Необходимо также...

Перегрузка операторов. Класс String
Зравствуйте! У меня есть вопрос. Реализовать класс String для работы со строками символов. Память под строку выделять автоматически....

Свой класс String
Небольшой набросок на класс String #include &lt;iostream&gt; #include &lt;cstring&gt; using namespace std; class String { struct...


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

Или воспользуйтесь поиском по форуму:
100
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru