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

Свой шаблонный класс string для char wchar_t, оптимизация

22.01.2024, 16:45. Показов 3190. Ответов 38

Студворк — интернет-сервис помощи студентам
Доброго времени суток.
Создал свой класс string. Цель создания своего класса строк - это скорость работы со строками и второе в образовательных целях. Если реализация получится удачной сделаю библиотеку для личного использования. new и delete решил не использовать, просьба не рекомендовать их. Представленный вариант пока в разработке, но тем не менее работает. Не хочу получить UB и пр. Просьба просмотреть и по возможности проверить. Жду ваших рекомендаций.

Кастомные функции для строк char wchar_t используются внутри класса :
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
#include <iostream>
 
#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 len_max = 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 && len_max--) 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;
}
Собственно мой класс строк:
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
/* Класс 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:
 
        size_t  leng{0U};           /* Количество символов в строке */
        size_t  size_str{0U};       /* Размер выделенной памяти для строки */     
        T       *p_str{nullptr};    /* Строка */
                
//------------------------------------------------------------------
void realloc_foo(size_t len, bool len_contr = true)
{
        T *p_str_t = nullptr; if ((len + 1) == size_str)return;
        /* Контроль минимального размера буфера */
        if (len_contr)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);                 
}
//------------------------------------------------------------------
void calloc_foo(size_t len = SIZE_STRING)
{   if(len > 0) size_str = len;
        T *p_str_t = nullptr;
        if ((p_str_t = static_cast<T *>(calloc(size_str, sizeof(T) ) ) ) != 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(const T *pstr, size_t len) {
            assert(pstr != nullptr);
            if(len  > 0U) { leng = len; malloc_foo(leng);               
                    custom_strncpy_s<T>(p_str, pstr, leng, size_str);
            }  
 }
 
/* Конструктор копирования */
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() {calloc_foo();}
 
~string() noexcept {
            if(p_str != nullptr)    free(p_str);    
            p_str = nullptr;        size_str = leng = 0U;  
}
/* Работа с размером.. */
//------------------------------------------------------------------
bool    empty()         const { assert(p_str != nullptr); return leng ? false : true;}
size_t  length()        const { assert(p_str != nullptr); return leng; }
//size_t    mem_buff()      const { return size_str; } /* Для тест памяти */
size_t  string_size()   const { assert(p_str != nullptr); return ((leng +  1) * sizeof(T)); }
//------------------------------------------------------------------
 
//------------------------------------------------------------------
/* Изменит размер выделенной памяти. Возможно линковать последов, можно делать цепочку вида: s.resize().add("52").c_str(); 
*   возможны нежелательные комбинации цепочек
*/
string<T>& resize(size_t n = SIZE_STRING)
{   assert(p_str != nullptr);
    if(n > 0)realloc_foo(n, false);
    return *this;
}
 
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти, можно делать цепочку s.add("1").add("2").add("3").add("4").c_str(); */
 
string<T>& add(const T *p_str_in)
{  
    assert(p_str_in != nullptr || p_str != nullptr); size_t len = 0;   
     if ((len = custom_strnlen<T>(p_str_in)) != 0U) { 
            realloc_foo(leng + len); 
            custom_strncat_s<T>(p_str, leng, p_str_in, len, size_str); leng += len;          
        } return *this;   
 
}
string<T>& add(const T *p_str_in, size_t len)
{  
    assert(p_str_in != nullptr || p_str != nullptr); 
    if (len > 0)
    {
        realloc_foo(leng + len);
        custom_strncat_s<T>(p_str, leng,  p_str_in, len, size_str); leng += len; 
    }return *this;
}
 
string<T>& add(const string<T>& s)
{     
    add(s.p_str, s.leng); return *this;
}
 
//------------------------------------------------------------------
/* Элементный доступ */
 
const   T & at(size_t i)    const   { assert(p_str != nullptr); return operator[](i);}
        T & at(size_t i)            { assert(p_str != nullptr); return operator[](i);}
const   T & front()         const   { assert(p_str != nullptr); return operator[](0);}
        T & front()                 { assert(p_str != nullptr); return operator[](0);}
const   T & back()          const   { assert(p_str != nullptr); return operator[](leng - 1);}
        T & back()                  { assert(p_str != nullptr); return operator[](leng - 1);}
 
//------------------------------------------------------------------
/* Прочее.. */
//------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable:6276)
const T* c_str() const { return (p_str != nullptr) ? p_str : (T*)'/0'; }
 
//------------------------------------------------------------------
/* Возможно линковать последов. s.clear().add("1").add("2").add("3").add("4").c_str(); */
string<T>&  clear() {   
    size_str =  SIZE_STRING ;
    realloc_foo(size_str - 1); 
    *p_str = (T)'\0'; leng = 0;
    return *this;
}
#pragma warning(pop)
 
/* Операторы доступа */
//------------------------------------------------------------------
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 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);
    }
//------------------------------------------------------------------ 
template<class T_, class T>friend T_ &operator << (T_ &ostr,    string<T> const &str);
 
template<class T_, class T>friend T_ &operator >> (T_ &in,  string<T> &str);
 
 friend  const string<T> operator + (const string<T> &l, const string<T> &r)        {return string<T>(l) += r;} 
 
 //------------------------------------------------------------------ 
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  */
};
 
    template<class T_ = std::ostream, class T > 
inline T_ &  operator << (T_ & ostr, str::string<T> const & str){ostr << str.c_str(); return ostr;}
 
 
    template<class T_ = std::istream, class T>
inline T_ & operator >> (T_ & in, str::string<T>  &str)
{
         /* test  >> test!! */
        str.clear();        
        T ch[1]{}; 
        auto c = -1;
    do {
        c = in.get();
        if (c == -1)break;
        *ch = static_cast<T>(c);
        str.add(ch, 1);
    } while (true);    
    return in;
}
 
 
 
//------------------------------------------------------------------
/* Конец области str:: */
};
где-то:
C++
1
2
str::string str(L"Привет ");
        str::string str2(L" Мир !");
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.01.2024, 16:45
Ответы с готовыми решениями:

Подскажите как доработать свой класс для строк wchar_t
Есть свой класс для строк. Нужна поддержка wchar_t. То есть я так понимаю нужно добавить конструктор STRING(const wchar_t* wch) для...

Преобразование между типами System::String, char*, wchar_t*, std::string и др.
При написании кода, взаимодействующего как с .NET и управляемым кодом, так и с неуправляемым кодом (такими как стандартные библиотеки C и...

Конвертация строк: System::String в массив char/wchar_t, std::string и обратно
How to: Convert System::String to wchar_t* or char* How to: Convert System::String to Standard String How to: Convert Standard String...

38
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
25.01.2024, 00:59  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Хотя это особо не важно. Представьте, что это псевдокод и берите идеи.
сделал для проверки по тому посту :
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
template <typename CharT = char, typename Traits>
inline std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& in, str::string<CharT>& str)
 
{
    static constexpr auto BUF = 260U;
    constexpr auto eof = Traits::eof();      
    auto c = eof; 
    
    size_t max_size = TRUNCATE;
    CharT ch_buf[BUF]{};
    CharT ch_b = Traits::to_char_type(' ');
    CharT ch_n = Traits::to_char_type('\n');
    std::ios::iostate err = std::ios::goodbit;
 
    in.seekg (0, in.end);
    size_t lengths = in.tellg();
    in.seekg (0, in.beg);
    str.resize(lengths); 
 
    size_t extracted = 0;
   try
    {
 
        size_t len = 0;
        const size_t  w = in.width();
        const size_t  n = w > 0 ? static_cast<size_t>(w) : lengths;
 
        
         c = in.rdbuf()->sgetc();
 
        while(extracted < n && !Traits::eq_int_type(c, eof) && Traits::to_char_type(c) != ch_b && Traits::to_char_type(c) != ch_n)
                
                
        {
            if(len == sizeof(ch_buf) / sizeof(CharT))
            {
                str.add(ch_buf, sizeof(ch_buf) / sizeof(CharT));
                len = 0;
                
            }
 
            ch_buf[len++] = Traits::to_char_type(c);
            ++extracted;
            c = in.rdbuf()->snextc();
        }
        str.add(ch_buf, len);
 
        if(Traits::eq_int_type(c, eof))err |= std::ios::eofbit; in.width(0);
            
        
    }
    catch(...)
    {
        in.clear(std::ios::badbit);
    }
    if(!extracted)
        err |= std::ios::failbit;
    if(err)
        in.clear(err);
    return in;
}
в майне:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
inf.imbue(std::locale("ru_RU.utf8"));
    if (!inf)
    {
        // то выводим следующее сообщение об ошибке и выполняем функцию exit()
        std::cerr << "Uh oh, SomeText.txt could not be opened for reading!" << std::endl;
        system("pause");
        exit(1);
    }
    str::string<wchar_t> strInput;
    // Пока есть данные, которые мы можем прочитать,
    /*while (inf)*/inf >> strInput; /* если цикл закомментирую то читает как положено до пробела или конца строки */
    /* в противном случае читает одну и тоже строку не выходя из цикла */
    inf.close();    
    std::wcout << strInput << L" \n\n\nLength :" <<  strInput.length() << L" <<<<<" << std::endl;
Добавлено через 3 минуты
Я наверно туплю сильно или чего-то не пойму как мне сделать? для представленного случая в тесте в майн

Добавлено через 11 минут
Я так понимаю мне нужно как-то вернуть сколько я прочитал и после этого смогу прочитать дальше.
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
25.01.2024, 07:47  [ТС]
вот я затупил --->
Цитата Сообщение от Signum7 Посмотреть сообщение
in.seekg (0, in.end);
    size_t lengths = in.tellg();
    in.seekg (0, in.beg);


Добавлено через 1 минуту
исправил все заработало
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
25.01.2024, 19:43  [ТС]
полностью рабочая перегрузка оператора >>. Добавил в класс делимитер, теперь можно читать до любого символа если делимитер равен нулю читаем весь файл. Вот реализация:
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
template <typename CharT = char, typename Traits>
inline std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& in, str::string<CharT>& str)
 
{
    static constexpr auto BUF = 1U;
    constexpr auto eof = Traits::eof();     
 
    using is   = std::basic_istream<CharT, Traits>;
    CharT ch_buf[BUF]{};    
    CharT ch_n = *str.get_delimiter();
    typename is::iostate state = is::goodbit;
    const typename is::sentry Ok(in);
    size_t max_size = TRUNCATE;
    bool changed  = false;
    auto c = eof; 
 
    if (Ok) { 
        _TRY_IO_BEGIN
        size_t size;
        if (0 < in.width() && static_cast<size_t>(in.width()) < max_size) {
            size = static_cast<size_t>(in.width());
        } else {
            size = max_size;
        }
 
        c = in.rdbuf()->sgetc();
        for (; 0 < size; --size, c = in.rdbuf()->snextc()) {
            
            if (Traits::eq_int_type(eof, c) ) {state |= is::eofbit; break;} 
                
              else {ch_buf[0] = Traits::to_char_type(c);                    
                
                    str.add(ch_buf, 1);
                    if(ch_n == Traits::to_char_type(c)) break;
                    changed = true;
            }
        }
        _CATCH_IO_(is, in)
    }
 
    in.width(0);
    if (!changed) {state |= is::failbit;}
    in.setstate(state); 
 
    return in;
}
Добавлено через 2 минуты
Как пример реализации распарсил библиотечный string, его реализация похожа на тот пример который был от DrOffset

Добавлено через 1 час 34 минуты
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Signum7, по меньшей мере - не менять состояние класса
переделал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool realloc_foo(size_t len, bool len_contr = true)
{
        T *p_str_t = nullptr; if ((len + 1) == size_str)return true;
        volatile size_t old_s = size_str;
 
        /* Контроль минимального размера буфера */
        if (len_contr)
            if(len < SIZE_STRING) size_str = SIZE_STRING; else  size_str = len + SIZE_STRING;
 
        if ((p_str_t = static_cast<T *> (realloc(p_str, (size_str) * sizeof(T)))) != nullptr) {
                p_str = p_str_t; 
                assert(p_str != nullptr); 
                return true;
        }size_str  = old_s; return false;
             
}
Вроде должно работать хорошо
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 18:29  [ТС]
Подскажите как правильно сделать функцию чтения строки с удалением прочитанной строки, я сделал так но наверно не оптимально или с ошибками.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define get_line(a, b) _get_line(a, b).get()->c_str()
std::unique_ptr <string<T>>_get_line(bool del_line = false, T delim = 0) const {assert(p_str != nullptr); 
 
    T ch_n = traits<T>::to_char_type(delim ? delim : (T)'\n');
    T* s_pos_n = const_cast<T*>(custom_strchr<T>(p_str, ch_n));
 
    size_t len_str = static_cast<size_t>((s_pos_n - p_str) + 1);
    if(del_line)
    {
        //p_str += len_str;
        //leng -= len_str;
    }
    return std::move(std::make_unique<string<T>>(p_str, len_str)); 
}
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
26.01.2024, 19:08
Цитата Сообщение от Signum7 Посмотреть сообщение
std::move
это тут точно лишнее

а про какое удаление речь ?
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 19:14  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
это тут точно лишнее

а про какое удаление речь ?
строка1
строка2
строка3
****
после get_line(del_line = true)
должна удалиться прочитанная строка

строка2
строка3
****
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
26.01.2024, 19:37
Цитата Сообщение от Signum7 Посмотреть сообщение
прочитанная строка
а где она ? И как она прочитана ?

Добавлено через 2 минуты
аа, дошло. Как-то так

C++
1
2
3
4
if(del_line)
{
      *this=string(p_str+len_str,leng - len_str);
}
надеюсь, оператор = такой есть и реализован правильно

Добавлено через 16 минут
Цитата Сообщение от Signum7 Посмотреть сообщение
malloc
раз уж тут используется сишная динамика, можно попробовать такую оптимизацию:

при помощи memmove сдвигаем хвост строки в начало на len_str элементов
затем вызываем realloc с новым размером leng - len_str

высока вероятность, что это всегда сработает (и realloc не вернёт 0)

но это увеличивает мусорный хвост блока памяти, выделенного под строку системой.

Ну, наверное, отдельно надо рассмотреть случай, когда строка станет нулевой длины

-----
выбирай, какой способ нравится больше
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 19:44  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
а где она ? И как она прочитана ?

Добавлено через 2 минуты
аа, дошло. Как-то так

C++
1
2
3
4
if(del_line)
{
      *this=string(p_str+len_str,leng - len_str);
}
надеюсь, оператор = такой есть и реализован правильно

Добавлено через 16 минут

раз уж тут используется сишная динамика, можно попробовать такую оптимизацию:

при помощи memmove сдвигаем хвост строки в начало на len_str элементов
затем вызываем realloc с новым размером leng - len_str

высока вероятность, что это всегда сработает (и realloc не вернёт 0)

но это увеличивает мусорный хвост блока памяти, выделенного под строку системой.

Ну, наверное, отдельно надо рассмотреть случай, когда строка станет нулевой длины

-----
выбирай, какой способ нравится больше
C2678 бинарный "=": не найден оператор, принимающий левый операнд типа "const str::string<wchar_t>" (или приемлемое преобразование отсутствует)

Вот все операторы:
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
/* Операторы  */
//------------------------------------------------------------------
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); f_swap (*this, tmp); return *this; }
 
        string<T> &operator = (string<T>&& moved)   noexcept    { f_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; }
 
//------------------------------------------------------------------ 
/* Друзья мои */
 
template <typename CharT, typename Traits>  
friend std::basic_ostream<CharT, Traits>    &operator << ( std::basic_ostream<CharT, Traits> & ostr,    str::string<CharT> const & str );
 
template <typename CharT, typename Traits>
friend std::basic_istream<CharT, Traits>    &operator >> ( std::basic_istream<CharT, Traits>& in,       str::string<CharT>& str );
 
//------------------------------------------------------------------
 
friend const string<T>  operator + (const string<T> &l, const string<T> &r) { return string<T>(l) += r; } 
 
 //------------------------------------------------------------------ 
friend bool operator < (const string<T>& l, const string<T>& r) noexcept { return custom_cscmp(l.c_str(), r.c_str()) < 0 ? true : false; }
 
friend bool operator > (const string<T>& l, const string<T>& r) noexcept { return custom_cscmp(l.c_str(), r.c_str()) > 0 ? true : false; }
 
friend bool operator == (const string<T> &l, const string<T> &r) noexcept { if(l.length() != r.length())return false;   
                                                                            return custom_cscmp(l.c_str(),r.c_str() ) == 0 ? true : false;
}
//------------------------------------------------------------------
Добавлено через 1 минуту
какие операторы еще нужно добавить?

Добавлено через 42 секунды
проверю пока сишный метод
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
26.01.2024, 19:48
Цитата Сообщение от Signum7 Посмотреть сообщение
std::unique_ptr <string<T>>_get_line(bool del_line = false, T delim = 0) const {assert(p_str != nullptr);
а чего у тебя функция то const?
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 19:52  [ТС]
сработало
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
26.01.2024, 19:53
Цитата Сообщение от Signum7 Посмотреть сообщение
какие операторы нужно добавить
такие, которые потребуются во время тестирования и применения класса. Там станет видно
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 19:53  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
а чего у тебя функция то const?
А блин точно, благодарю. Но все равно посмотрите если не сложно, может какие операторы нужно добавить ?
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
26.01.2024, 19:59
Signum7, почему-то сообщения местами переставились
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
26.01.2024, 20:01  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Signum7, почему-то сообщения местами переставились
точно
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
27.01.2024, 15:07  [ТС]
Создал для своего класса итератор, подскажите на сколько там все правильно для моего класса.
класс итератор:
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
template<class T>
class string_iterator
{
public:
   typedef T value_type;
   typedef T* pointer;
   typedef T& reference;
   typedef std::forward_iterator_tag iterator_category;
   typedef ptrdiff_t difference_type;
   string_iterator() = default;
   string_iterator(T* curr):current(curr)
   {
   }
   string_iterator& operator =(const string_iterator& other)
   {
       if (this != &other)
       {
           current = other.current;
       }
       return *this;
   }
   string_iterator& operator ++()
   {
       ++current;
       return *this;
   }
   string_iterator operator ++(int i)
   {
       string_iterator tmp(current);
       ++current;
       return tmp;
   }
   T& operator *()
   {
      return *current;
   }
   T* operator ->()
   {
      return current;
   }
   bool operator ==(const string_iterator& other)
   {
      return current == other.current;
   }
   bool operator !=(const string_iterator& other)
   {
      return !(*this == other);
   }
private:
    T* current{0};
};
Внутри моего класса:
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
/* Класс 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 ");
 
/* Итератор  */
//------------------------------------------------------------------
public: 
        typedef string_iterator<T> iterator;
        typedef size_t size_type;
        typedef T* pointer;
        typedef const T* const_pointer;
        typedef T& reference;
        typedef const T& const_reference;
        typedef T value_type;
 
        string_iterator<T> begin()
        {
           return string_iterator<T>(p_str);
        }
        string_iterator<T> end()
        {
           return string_iterator<T>(p_str + leng);
        }
//------------------------------------------------------------------
Буду признателен за помощь так как с итераторами раньше не сталкивался.
Для моего класса такая конструкция работает:

C++
1
2
3
4
5
6
        str::string str(L"Привет ");
        ***
    for (auto s : str)
    {
    std::wcout << L" for " << s << std::endl;
    }
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
27.01.2024, 15:09
Signum7, было бы логично разместить класс внутри str::string и назвать iterator
1
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
27.01.2024, 18:56  [ТС]
класс в доработке еще но вот выкладываю то, что на данный момент:
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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
//===================================================================================================================
/* Класс 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:
template<class T>
class string_iterator
{
public:
    typedef T                           value_type;
    typedef T                           *pointer;
    typedef T                           &reference;
    typedef std::forward_iterator_tag   iterator_category;
    typedef ptrdiff_t                   difference_type;
    
    string_iterator() = default;
    string_iterator(T *curr) : current(curr){}   
    
    string_iterator& operator = ( const string_iterator &other)
    {
        if (this != &other)
        {
            current = other.current;
        }
        return *this;
    }
    string_iterator &operator ++()
    {
        ++current;
        return *this;
    }
    string_iterator operator ++(int i)
    {
        string_iterator tmp(current);
        ++current;
        return tmp;
    }
        T &operator *()     { return *current; }   
        T *operator ->()    { return current; }      
    
    bool operator == (const string_iterator &other )
    {
        return current == other.current;
    }
    bool operator != ( const string_iterator &other )
    {
        return !( *this == other );
    }
private:
    T* current{0};
};
//------------------------------------------------------------------
 
typedef string_iterator<T> iterator;
typedef string_iterator<T> const_iterator;
public:         
        typedef size_t      size_type;
        typedef T           *pointer;
        typedef const T     *const_pointer;
        typedef T           &reference;
        typedef const T     &const_reference;
        typedef T           value_type;
 
        iterator begin()    { assert(p_str != nullptr); return iterator(p_str); }       
        iterator end()      { assert(p_str != nullptr); return iterator(p_str + leng); }           
        
        const_iterator begin()  const   { return begin(); }     
        const_iterator end()    const   { return end(); }          
        
//------------------------------------------------------------------
private:
 
        size_t  leng{0U};           /* Количество символов в строке */
        size_t  size_str{0U};       /* Размер выделенной памяти для строки */     
        T       *p_str{nullptr};    /* Строка */
        T       str_delimiter[1]{};
                
template<class T = char>
using traits   = std::char_traits<T> ;
//------------------------------------------------------------------
bool realloc_foo(size_t len, bool len_contr = true)
{
        T *p_str_t = nullptr; if ((len + 1) == size_str)return true;
        volatile size_t old_s = size_str;
 
        /* Контроль минимального размера буфера */
        if (len_contr)
            if(len < SIZE_STRING) size_str = SIZE_STRING; else  size_str = len + SIZE_STRING;
 
        if ((p_str_t = static_cast<T *> (realloc(p_str, (size_str) * sizeof(T)))) != nullptr) {
                p_str = p_str_t; 
                assert(p_str != nullptr); 
                return true;
        }size_str  = old_s; return false;
             
} 
//------------------------------------------------------------------
bool malloc_foo(size_t len)
{  
    T *p_str_t = nullptr; volatile size_t old_s = size_str;
 
    if(len < SIZE_STRING) size_str = SIZE_STRING; else size_str = len + SIZE_STRING;        
 
        if ((p_str_t = static_cast<T *>(malloc(sizeof(T) * (size_str) ) ) ) != nullptr) {
            p_str = p_str_t;
            assert(p_str != nullptr);
            return true;
        }size_str  = old_s; return false;                
}
//------------------------------------------------------------------
bool calloc_foo(size_t len = SIZE_STRING)
{   
    T *p_str_t = nullptr; volatile size_t old_s = size_str;
    if(len > 0) size_str = len; else size_str += 1;
        
        if ((p_str_t = static_cast<T *>(calloc(size_str, sizeof(T) ) ) ) != nullptr) {
            p_str = p_str_t;
            assert(p_str != nullptr);
            return true;
        }size_str  = old_s; return false;  
} 
//------------------------------------------------------------------
public:
/* Конструкторы: */
/* Конструктор символы */
string(const T *pstr) {
            assert(pstr != nullptr); size_t len = 0U;
            if((len = CUS::custom_strnlen<T>(pstr) ) > 0U) { 
                if(malloc_foo(len)) 
                {leng = len; CUS::custom_strncpy_s<T>(p_str, pstr, leng, size_str);}
            }  
 }
 
string(const T *pstr, size_t len) {
            assert(pstr != nullptr);
            
                if(malloc_foo(len)) {
                    leng = len; CUS::custom_strncpy_s<T>(p_str, pstr, leng, size_str);
                }
             
 }
 /* Конструктор .. */
 
string( T ch, size_t len) { if( calloc_foo(len) ) { push_back(ch); } }
explicit string(size_t len = 1U) { calloc_foo(len); }
/* Конструктор копирования */
string(const string<T>& s) {    
    leng  = s.leng; realloc_foo(leng);
    CUS::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;  
}
/* Работа с размером.. */
//------------------------------------------------------------------
bool    empty()         const { assert(p_str != nullptr); return leng ? false : true;}
 
size_t  length()        const { assert(p_str != nullptr); return leng; }
size_t  max_size()      const { return TRUNCATE;}
/* Размер строки в байтах */
size_t  string_size()   const { assert(p_str != nullptr); return ((leng +  1) * sizeof(T)); }
/* Возвращает количество символов, которое строка может хранить без дополнительного перевыделения памяти; */
size_t  capacity()      const { return size_str - leng - 1;}
 
/* Изменит размер выделенной памяти. Возможно линковать последов, 
*   можно делать цепочку вида: s.reserve().add("52").c_str(); 
*   возможны нежелательные комбинации цепочек
*/
string<T>& reserve(size_t n = SIZE_STRING)
{   assert(p_str != nullptr);
    if(n > 0)realloc_foo(n, false);
    return *this;
}
/* 
*   Очистка строки: full_clean = True очистит память размером len и затрет данные 0, 
*       в противном случае перевыделет память размером len и обнулит строку 
*           Возможно линковать последов. s.clear().add("1").add("2").add("3").add("4").c_str(); 
*/
string<T>&  clear(size_t len = 1U, bool full_clean = true) { assert(p_str != nullptr);  
    
    if(full_clean){
        if(calloc_foo(len))leng = 0;
    }else   
        if(realloc_foo(len)){
            *p_str = traits<T>::to_char_type('\0'); leng = 0;}
    return  *this;
}
//------------------------------------------------------------------
/* Элементный доступ */
 
const   T &at(size_t i) const       { assert(p_str != nullptr); return operator[](i);}
        T &at(size_t i)             { assert(p_str != nullptr); return operator[](i);}
const   T &front()      const       { assert(p_str != nullptr); return operator[](0);}
        T &front()                  { assert(p_str != nullptr); return operator[](0);}
const   T &back()       const       { assert(p_str != nullptr); return operator[](leng - 1);}
        T &back()                   { assert(p_str != nullptr); return operator[](leng - 1);}
 
//------------------------------------------------------------------
    /* вставляет символы в произвольный индекс строки */
string<T> &insert_ch()      { assert(p_str != nullptr); /* Доделать!!! Доделать!!!*/ return *this; }
 
    /* Удаляет символы по произвольному индексу строки */
string<T> &erase_ch()       { assert(p_str != nullptr); /* Доделать!!! Доделать!!!*/ return *this; }
 
/* Расширяет или уменьшает строку 
*   (удаляет или добавляет символы в конце строки)
*/
string<T> &resize_str()     { assert(p_str != nullptr); /* Доделать!!! Доделать!!!*/ return *this; }
 
    /* Меняет местами значения двух строк. */
string<T> &swap_str( string<T>& l, string<T>& r )       { assert(p_str != nullptr); f_swap(l, r);       return  *this; }
string<T> &swap_str( string<T>& r)                      { assert(p_str != nullptr); f_swap(*this, r);   return  *this; }
 
string<T> &swap_str( T * r)     { assert(p_str != nullptr);     
        string<T> tmp(r); 
 
        swap_str(*this, tmp);   
        r = std::move(tmp.c_str()); 
        return  *this; 
}
 
    /* Заменяет символы произвольных индексов строки другими символами */
string<T> &replace(T ch1, T ch2, size_t elm = 0) { assert(p_str != nullptr); CUS::custom_replace<T>(p_str, ch1, ch2, (elm ? elm : leng)); return    *this; }
 
string<T> &replace(const T* str1, const T* str2, size_t elm = 0){assert(p_str != nullptr); /* Доделать!!! Доделать!!!*/ return  *this;}
string<T> &replace(string<T>& str1, string<T>& str2, size_t elm = 0){assert(p_str != nullptr); /* Доделать!!! Доделать!!!*/ return  *this;}
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти, 
        можно делать цепочку s.add("1").add("2").add("3").add("4").c_str(); */
 
string<T> &add(const T *p_str_in)
{  
    assert(p_str_in && p_str); size_t len = 0;   
     if ((len = CUS::custom_strnlen<T>(p_str_in)) != 0U) { 
            if(realloc_foo(leng + len)) 
                {CUS::custom_strncat_s<T>(p_str, leng, p_str_in, len, size_str); leng += len; }
        } return *this; 
}
/* -- */
string<T> &add(const T *p_str_in, size_t len)
{  
    assert(p_str_in && p_str); 
    if (len > 0)
    {
        if(realloc_foo(leng + len))
            { CUS::custom_strncat_s<T>(p_str, leng,  p_str_in, len, size_str); leng += len;} 
    } return *this;
}
/* -- */
string<T> &add(const string<T>& s) { add(s.p_str, s.leng); return *this; }  
 
string<T> &push_back(T ch) { *tmp = traits<T>::to_char_type(ch);    add(tmp, 1);    return *this; } /* Добавляет символ к концу строки */
 
//------------------------------------------------------------------
/* Прочее.. */
//------------------------------------------------------------------
        T   get_delimiter()         { return *str_delimiter ; }
bool        delimiter_is_0()        { return (*str_delimiter == 0); }
void        set_delimiter( T delim) { *str_delimiter = traits<T>::to_char_type(delim); }
//------------------------------------------------------------------
/* Чтение всей строки из памяти */
const   T   *c_str() const {assert(p_str != nullptr); return  p_str ; }
 
 
/* Чтение строки с учетом разделителя */
/* Оптимизировать ! потом может =)) */
std::unique_ptr <string<T>>_get_line(bool del_line = false, T delim = 0) {assert(p_str != nullptr); 
 
    T ch_n = traits<T>::to_char_type(delim ? delim : (T)'\n')
        ;
    if(*p_str == 0)return std::make_unique<string<T>>(1);
 
    T* s_pos_n = const_cast<T*>(CUS::custom_strchr<T>(p_str, ch_n));
    
    size_t len_str = static_cast<size_t>((s_pos_n - p_str) + 1);
 
auto ptr = std::make_unique<string<T>>(p_str, len_str);
    if(del_line)
        {
            *this = std::move(string<T>(p_str + len_str, leng - len_str));
        }
        return ptr;
#define get_line(a, b)  _get_line(a, b).get()->c_str()
}
//------------------------------------------------------------------
/* Операторы  */
//------------------------------------------------------------------
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); f_swap (*this, tmp); return *this; }
        string<T> &operator = (string<T>&& moved)   noexcept    { f_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 const string<T>  operator + (const string<T> &l, const string<T> &r) { return string<T>(l) += r; } 
 
 //------------------------------------------------------------------ 
friend bool operator    <   (const string<T> &l, const string<T>& r) noexcept { return CUS::custom_cscmp(l.c_str(), r.c_str()) < 0 ? true : false; }
friend bool operator    >   (const string<T> &l, const string<T>& r) noexcept { return CUS::custom_cscmp(l.c_str(), r.c_str()) > 0 ? true : false; }
friend bool operator    >=  (const string<T> &l, const string<T> &r) noexcept {return !(l < r);}
friend bool operator    <=  (const string<T> &l, const string<T> &r) noexcept {return !(l > r);}
friend bool operator    !=  (const string<T> &l, const string<T> &r) noexcept {return !(l == r);}
friend bool operator    ==  (const string<T> &l, const string<T> &r) noexcept { if(l.length() != r.length())return false;   
                                                                                    return CUS::custom_cscmp(l.c_str(),r.c_str() ) == 0 ? true : false; }
//------------------------------------------------------------------ 
 
template <typename CharT, typename Traits>  
friend std::basic_ostream<CharT, Traits>    &operator << ( std::basic_ostream<CharT, Traits> &ostr, str::string<CharT> const & str );
 
template <typename CharT, typename Traits>
friend std::basic_istream<CharT, Traits>    &operator >> ( std::basic_istream<CharT, Traits>&in,        str::string<CharT>& str );
//------------------------------------------------------------------
 
private:
void f_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);        
    }
//------------------------------------------------------------------
protected:
T* s_ptr()                      { assert(p_str != nullptr);  return p_str; }
size_t  mem_buff()  const       { return size_str; } /* Для тест памяти */
T tmp[32]{};
 
 
//------------------------------------------------------------------ 
#ifdef SIZE
#undef SIZE
#endif
/* Конец string  */
};
//------------------------------------------------------------------ 
 
template <typename CharT = char, typename Traits>   
inline std::basic_ostream<CharT, Traits> &  operator << (std::basic_ostream<CharT, Traits> & ostr, str::string<CharT> const & str){ ostr << str.c_str(); return ostr; }
//------------------------------------------------------------------ 
 
template <typename CharT = char, typename Traits>
inline std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& in, str::string<CharT>& str)
 
{
    static constexpr auto BUF = 1U;
    static constexpr auto eof = Traits::eof();      
 
    using is   = std::basic_istream<CharT, Traits>;
    CharT ch_buf[BUF]{};    
    CharT ch_n = str.get_delimiter();
    typename is::iostate state = is::goodbit;   
    const typename is::sentry Ok(in);
    size_t max_size = TRUNCATE;
    bool changed  = false;
    auto c = eof; 
 
    if (Ok) { 
        _TRY_IO_BEGIN
        size_t size;
        if (0 < in.width() && static_cast<size_t>(in.width()) < max_size) {
            size = static_cast<size_t>(in.width());
        } else {
            size = max_size;
        }
 
        c = in.rdbuf()->sgetc();
        for (; 0 < size; --size, c = in.rdbuf()->snextc()) {
            
            if (Traits::eq_int_type(eof, c) ) {state |= is::eofbit; break;} 
                
              else {ch_buf[0] = Traits::to_char_type(c);                    
                
                    str.add(ch_buf, 1);
                    if(ch_n == Traits::to_char_type(c)) break;
                    changed = true;
            }
        }
        _CATCH_IO_(is, in)
    }
 
    in.width(0);
    if (!changed) {state |= is::failbit;}
    in.setstate(state); 
 
    return in;
}
//------------------------------------------------------------------
/* Конец области str:: */
};
Добавлено через 38 минут
кастомные функции для класса
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
#include <iterator>
 
#include <iostream>
#include <fstream>
#include <istream>
 
#include <type_traits>
#include <cassert>
 
namespace str
{
//#define SIZE 10000
 
static constexpr   size_t  TRUNCATE = ((size_t)-1);
static constexpr   bool STACK_STRING = false ;
#ifndef SIZE
static constexpr   size_t SIZE_STRING = 260 ; /* символов */
#else
static constexpr   size_t SIZE_STRING = SIZE ;
#if (SIZE < 260)
static constexpr   bool STACK_STRING = true ; /* Возможно для маленьких строк сделаю на стеке */
#else
static constexpr   bool STACK_STRING = false ;
#endif
#endif
namespace CUS{
//------------------------------------------------------------------
/* возвращает указатель на первый символ ch в строке*/
template <class T = char> 
const T* custom_strchr(const T* str, T ch)  /* 'requires' --> C++20 */
    //requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{   if(*str == 0)return str;
    const T *p;
    for (p = str; *p && *p != ch; p++);
    return p;
}
 
//------------------------------------------------------------------
/* Длина строки (количество символов без нуля) */
template <class T = char> 
inline size_t custom_strnlen(const T* str,size_t len_max = 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 && len_max--) 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 && strc);
 
  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 && strc);    
    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 && strc);    
    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 && str2);
 
    while ( *str1 && *str1 == *str2 ) ++str1, ++str2;       
    return *str1 - *str2;
}
//------------------------------------------------------------------
template <class T = char> 
inline void custom_replace( T* str,  T prev_ch , T new_ch, size_t elem_count = 0U) 
    //requires(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>)
{
    assert(str);
    if(elem_count == 0U) elem_count = custom_strnlen<T>(str);
    T* str1 = str; 
    while (*str1 && elem_count--)
    {
        if(*str1 == prev_ch)*str1 = new_ch;
            str1++;     
    }
    
}
}
//------------------------------------------------------------------
 
#pragma warning(push)
#pragma warning(disable:4996)
#pragma warning(pop)
 
//===================================================================================================================
/* Класс string только для строк  char или wchar_t */
template<class T = char>
class string
Добавлено через 55 минут
понял почему так предлагаете:
Цитата Сообщение от Алексей1153 Посмотреть сообщение
1
~string() noexcept { free(p_str); }
Функция free освобождает место в памяти. Блок памяти, ранее выделенный с помощью вызова malloc, calloc или realloc освобождается. То есть освобожденная память может дальше использоваться программами или ОС.

Обратите внимание, что эта функция оставляет значение ptr неизменным, следовательно, он по-прежнему указывает на тот же блок памяти, а не на нулевой указатель.

Параметры:
ptrmem
Указатель на блок памяти, ранее выделенный функциями malloc, calloc или realloc, которую необходимо высвободить. Если в качестве аргумента передается нулевой указатель, никаких действий не происходит.
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
29.01.2024, 14:06  [ТС]
Оптимизировал выделение памяти теперь использую амортизацию размера выделенной памяти :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool realloc_foo(size_t len, bool len_contr = true)
{
        T *p_str_t = nullptr; 
        size_t old_s = size_str;
 
    if (len_contr)  {
                        if ((len + 1) <= size_str) return true;
                        if(len < SIZE_STRING) size_str = SIZE_STRING; else  size_str = (len + SIZE_STRING) << 1;
                    } else size_str = len;
 
        if ((p_str_t = static_cast<T *> (realloc(p_str, (size_str) * sizeof(T)))) != nullptr) { 
                p_str = p_str_t; 
                assert(p_str != nullptr); 
                return true;
        }size_str  = old_s; return false;             
}
Работает вроде правильно, но меня смущает много ifов в данной функции.
0
1 / 1 / 0
Регистрация: 30.03.2017
Сообщений: 141
30.01.2024, 18:23  [ТС]
Помогите мне пожалуйста заполнить правильно итератор random_access_iterator для моего класса:
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
/* Класс 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:
template<class T>
class string_iterator
{
public:
 
    using value_type        =   T;  
    using iterator_category =   std::random_access_iterator_tag;                    
    using difference_type   =   ptrdiff_t;
    using pointer           =   T*;
    using reference         =   T&;
    
                string_iterator()           noexcept = default;
    explicit    string_iterator(T *curr)    noexcept : current(curr){}   
    
    string_iterator& operator = ( const string_iterator &other)
    {
        if (this != &other)
        {
            current = other.current;
        }
        return *this;
    }
    string_iterator &operator ++()
    {
        ++current;
        return *this;
    }
    string_iterator operator ++(int i)
    {
        string_iterator tmp(current);
        ++current;
        return tmp;
    }
    string_iterator &operator --()
    {
        --current;
        return *this;
    }
    string_iterator operator --(int i)
    {
        string_iterator tmp(current);
        --current;
        return tmp;
    }
 
        // Операции, необходимые для RandomAccessIterator.
    reference operator[](difference_type n) const { auto tmp = *this; tmp += n; return *tmp; }
    string_iterator& operator+=(difference_type n) { /* что тут */return *this; }
    string_iterator& operator-=(difference_type n) { return *this += -n; }
 
        reference   operator *()    const   noexcept { return *current; }   
        pointer     operator ->()   const   noexcept { return current; }      
    
    bool operator == (const string_iterator &other )
    {
        return current == other.current;
    }
    bool operator != ( const string_iterator &other )
    {
        return !( *this == other );
    }
private:
    pointer current{0};
};
//------------------------------------------------------------------
 
 
public:
            
        using iterator          = string_iterator<T>;   
        using const_iterator    = string_iterator<const T>;
        using size_type         = size_t;
        using pointer           = T *;      
        using const_pointer     = const T *;
        using reference         = T &;
        using const_reference   = const T &;
        using value_type        = T; 
                        
 
        iterator begin()            noexcept { assert(p_str);   return iterator(p_str); }       
        iterator end()              noexcept { assert(p_str);   return iterator(p_str + leng); }           
        
        const_iterator cbegin()     const   noexcept { return const_iterator(p_str); }      
        const_iterator cend()       const   noexcept { return const_iterator(p_str + leng); }   
 
        iterator rbegin()           noexcept { assert(p_str);   return iterator(p_str + leng); }        
        iterator rend()             noexcept { assert(p_str);   return iterator(p_str); }          
        
        const_iterator crbegin()    const   noexcept {return const_iterator(p_str + leng);}     
        const_iterator crend()      const   noexcept {return const_iterator(p_str);}    
        
//------------------------------------------------------------------
private:
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.01.2024, 18:23

Создать шаблонный класс для преобразования массивов из типа int в char.
Хелп как это сделать сиджу уже 2 дня и голову ломаю Создать шаблонный класс для преобразования массивов из типа int в char. нужно на с++

По поводу wchar_t, wstring, char, string и кодировок
Здравствуйте, пишу консольную либу которая будет работать с большим количеством символов в разных алфавитах, и кроссплатформенно, как я...

Шаблонный класс динамического массива. Тип элементов char*
Я тут в ступоре... Вот мое полное задание: В данной лабораторной работе необходимо разработать шаблонный класс в соответствии с ...

Создать строковый шаблонный класс String
Сделайте класс String шаблонным. В исходном классе замените конструктор с 1 параметром на конструктор с 2 параметрами (указатель на массив...

как переделать шаблонный класс-стек в шаблонный класс-очередь !
Есть класс-контейнер стек с сортировкой , а нужно класс-контейнер очередь ! как переделать ?? подскажите #include &quot;queue.h&quot; ...


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

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru