Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Обработка строк или как сделать свой велосипед

08.10.2020, 14:17. Показов 944. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех! Уважаемые, подскажите грамотное решение проблемы.

При разработке мне очень часто приходится работать со структурами, которые, в частности, содержат поля, представляющие собой массивы char. По сути это строки фиксированной длины, только у них нет завершающего 0 и пустая строка - это пробелы (соответственно, если в строке длиной 10 с начала содержится текст "Hello", то остальные 5 символов это пробелы).

Я думал о применении std::string, однако данный вариант имеет проблемы с оптимальностью (а это очень важно, так как в программе надо обрабатывать сотни тысяч таких "строк"):
1) сначала надо создать переменную std::string, скопировав туда массив;
2) затем удалить в этой переменной пробелы в конце;
3) после полезной работы с переменной ее содержимое надо скопировать обратно в поле структуры;
4) и, наконец, заполнить пробелами "пустое" место в поле структуры.

Чтобы избежать операций копирования, я думаю о создании шаблонного класса строки, который обрабатывал бы строку "на месте". В конструкторе класса можно было бы указать начало строки и ее размер. Это убирает выше указанные п. 1 и 3. Чтобы можно было делать что-то типа такого:
C++
1
2
3
4
5
6
7
struct Data {
  char field[10];
};
 
Data data;
MyStr<sizeof(Data.field)> myStr(data.field);
myStr += "add";
Однако, мне хочется большего: создавать свои структуры из MyStr. Но эти структуры, с точки зрения расположения данных в них, должны быть идентичны "обычным" структурам. То есть:
C++
1
2
3
4
5
6
7
8
9
struct Data {
  char field[10];
} data;
 
struct Data2 {
  MyStr<10> field;
} data2;
 
sizeof(data) == sizeof(data2) /* Должно быть истиной */
Скажите, такой класс, как MyStr, вообще возможно создать?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.10.2020, 14:17
Ответы с готовыми решениями:

Yii2 createObject и свой велосипед
Значит смотрите, не понимаю как работает createObject у Yii2 и зачем для начала, если не сложно дайте ответ. Потом я делаю свой...

Велосипед / Свой движок и шаблоны
Добрый день друзья. Делаю лабораторную в институте... короче говоря создаю сайт статистики. Тут собственно работа и с PHP, JQ, MYSQL, AJAX...

обработка строк как сделать
2. Задано предложение, состоящее из слов, разделённым одним или несколькими пробелами. Найти самое длинное слово в предложении

19
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
08.10.2020, 15:09
Цитата Сообщение от d7d1cd Посмотреть сообщение
Скажите, такой класс, как MyStr, вообще возможно создать?
Посмотри в сторону std::string_view
2
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
08.10.2020, 15:48  [ТС]
oleg-m1973, смотрел. Но через string_view нельзя менять строку. Плюс у меня заморочка с пробелами.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
08.10.2020, 15:59
Цитата Сообщение от d7d1cd Посмотреть сообщение
oleg-m1973, смотрел. Но через string_view нельзя менять строку. Плюс у меня заморочка с пробелами.
Просто сделай класс наподобие, он простейший. Удалять пробелы не обязательно, там длина строки указывается.

Добавлено через 1 минуту
Т.е. в твоей MyStr не копируй строку, а храни указатель на начало, длину строки и полный размер строки (длина строки + пробелы)

Добавлено через 5 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyStr
{
public:
    template <size_t Size>
    MyStr(char (&str)[Size])
    : m_str(str)
    , m_cap(Size)
    {
        m_ln = .......................;
    }
}
protected:
    char *m_str = nullptr;
    size_t m_ln = 0;
    size_t m_cap = 0;
};
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
08.10.2020, 16:21  [ТС]
oleg-m1973, но тогда не получится это:
Цитата Сообщение от d7d1cd Посмотреть сообщение
Однако, мне хочется большего: создавать свои структуры из MyStr. Но эти структуры, с точки зрения расположения данных в них, должны быть идентичны "обычным" структурам.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
08.10.2020, 16:34
Цитата Сообщение от d7d1cd Посмотреть сообщение
oleg-m1973, но тогда не получится это:
Сделай ещё один класс, который будет работать с такими строками. Это тоже несложно.
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
08.10.2020, 16:40
Цитата Сообщение от d7d1cd Посмотреть сообщение
Скажите, такой класс, как MyStr, вообще возможно создать?
1. возьми string_view
2. повыкидывай из него ненужное
3. добавь необходимое.

4. PROFIT???!!!!
2
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
08.10.2020, 16:55  [ТС]
hoggy, да, это отличный вариант, когда надо работать с уже имеющимся массивом (строкой). А мне надо, чтобы можно было создать объект такого класса на пустом месте, указав длину строки. Причем размер такого объекта должен быть равен размеру строки.
То есть, класс должен уметь работать и с имеющимся массивом чаров, и уметь создавать свой внутри себя. Наверное, это не получится реализовать в одном классе, но есть же наследование.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
08.10.2020, 17:03
Цитата Сообщение от d7d1cd Посмотреть сообщение
То есть, класс должен уметь работать и с имеющимся массивом чаров, и уметь создавать свой внутри себя. Наверное, это не получится реализовать в одном классе, но есть же наследование.
Здесь достаточно одного, аналога string_view, который я показал. Через него можно будет работать с обычными массивами и строками. Т.е. в структурах необязательно что-то менять.

Добавлено через 3 минуты
C++
1
2
3
4
5
6
7
8
9
10
class Data 
{
public:
    MyStringView GetField() 
    {
        return MyStringView(field);
    }
private:
    char field[10];
};
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.10.2020, 16:34  [ТС]
В общем, благодаря помощи, родилось вот такое решение (начало):
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
template<class T>
class IDb2StringBase
{
  public:
  size_t Size() { return static_cast<T*>(this)->GetSize(); }  
  
  private:
  char*  Ptr()  { return static_cast<T*>(this)->GetPtr(); }         
};
 
 
class IDb2StrRef : public IDb2StringBase<IDb2StrRef>
{
  friend IDb2StringBase<IDb2StrRef>;
  
  public:
  template <size_t N>
  IDb2StrRef(char (&data)[N]) : m_data(data), m_size(N) {}
  
  private:
  char*  GetPtr()        { return m_data; }
  size_t GetSize() const { return m_size; }  
  char*  const m_data;
  size_t const m_size;
}; 
 
 
template<size_t N>
class IDb2String : public IDb2StringBase< IDb2String<N>>
{
  static_assert(N > 0, "The size of the array cannot be 0.");
  friend IDb2StringBase<IDb2String<N>>;
  
  private:
  char*  GetPtr()        { return m_data; }
  size_t GetSize() const { return sizeof(m_data); }  
  char   m_data[N];
};
Использование:
C++
1
2
3
4
5
6
7
8
9
10
11
int main(int argc, char** argv)
{
  char data[5];
  IDb2StrRef db2ref(data);
  printf("sizeof(db2ref) = %d\n", sizeof(db2ref));
  printf("db2ref.Size()  = %d\n", db2ref.Size());  
  
  IDb2String<4> db2str;
  printf("sizeof(db2str) = %d\n", sizeof(db2str));
  printf("db2str.Size()  = %d\n", db2str.Size());
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.10.2020, 16:42
Цитата Сообщение от d7d1cd Посмотреть сообщение
В общем, благодаря помощи, родилось вот такое решение (начало):
Зачем наследоваться от IDb2StringBase?

Добавлено через 3 минуты
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
template<size_t N>
class IDb2String
{
    static_assert(N > 0, "The size of the array cannot be 0.");
 
    IDb2String()
    {
        std::fill(std::begin(m_data), std::end(m_data), ' ');
    }
 
    char*  GetPtr()        { return m_data; }
    size_t GetSize() const { return std::size(m_data); }  
 
    IDb2StrRef ref() const
    {
        return IDb2StrRef(m_data);
    }
 
    operator IDb2StrRef() const
    {
        return ref;
    }
 
 
private:
      char m_data[N];
};
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.10.2020, 16:52  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Зачем наследоваться от IDb2StringBase?
В этом классе будет реализована вся функциональность классов IDb2StrRef и IDb2String. Сами эти классы уже, скорее всего, не будут меняться. Они готовы.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.10.2020, 16:55
Цитата Сообщение от d7d1cd Посмотреть сообщение
В этом классе будет реализована вся функциональность классов IDb2StrRef и IDb2String.
Нет, не будет. Этот класс не нужен.

Цитата Сообщение от d7d1cd Посмотреть сообщение
Сами эти классы уже, скорее всего, не будут меняться. Они готовы.
Что-то не очень они похожи на готовые
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.10.2020, 18:55
Цитата Сообщение от d7d1cd Посмотреть сообщение
char*  const m_data;
  size_t const m_size;
у него не должно быть данных-членов за исколючением одного единственного и обязательного:

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
char m_data[N];

если ты нарушишь это положение,
тогда ты нарушишь своё собственное требование,
ради которого всего это затевается:

Цитата Сообщение от d7d1cd Посмотреть сообщение
с точки зрения расположения данных в них, должны быть идентичны "обычным" структурам.
что качается Олеговской версии:
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
size_t GetSize() const { return std::size(m_data); }
noexcept ? не, не слышал.
constexpr ? не, не слышал.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.10.2020, 20:52  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Нет, не будет. Этот класс не нужен.
Где делать реализацию тогда?

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Что-то не очень они похожи на готовые
Если будет базовый класс, то готовые.

Цитата Сообщение от hoggy Посмотреть сообщение
у него не должно быть данных-членов за исключением одного единственного и обязательного:
Цитата Сообщение от hoggy Посмотреть сообщение
если ты нарушишь это положение,
"У него" это у класса? У класса IDb2String нет данных-членов, за исключением одного. Класс IDb2String не нарушает это положение.

oleg-m1973, в представленном мной решении класс IDb2StrRef предназначен для работы с имеющимся массивом чаров, класс IDb2String предназначен для создания массива чаров и работы с ним.
Может я чего-то не понимаю в твоих доводах, но как твой последний пример будет работать с имеющимся массивом?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.10.2020, 23:24
Цитата Сообщение от d7d1cd Посмотреть сообщение
oleg-m1973, в представленном мной решении класс IDb2StrRef предназначен для работы с имеющимся массивом чаров, класс IDb2String предназначен для создания массива чаров и работы с ним.
Может я чего-то не понимаю в твоих доводах, но как твой последний пример будет работать с имеющимся массивом?
Я говорил про базовый класс IDb2StringBase.
У IDb2StrRef и IDb2String нет и не должно быть общего базового класса
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.10.2020, 07:49  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
У IDb2StrRef и IDb2String нет и не должно быть общего базового класса
Хорошо. Допустим у них не будет общего базового класса. Допустим мне надо добавить в эти классы функционал по очистке строки (в моей задаче это заполнение ее пробелами). Так как у классов нет общего предка, то реализацию надо делать и в одном и во втором классе?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
10.10.2020, 11:01
Цитата Сообщение от d7d1cd Посмотреть сообщение
Хорошо. Допустим у них не будет общего базового класса. Допустим мне надо добавить в эти классы функционал по очистке строки (в моей задаче это заполнение ее пробелами). Так как у классов нет общего предка, то реализацию надо делать и в одном и во втором классе?
Методы работают с переменными класса. Ты не сможешь сделать реализацию методов в базовом классе, а переменные объявить в наследниках.
Кстати, а нафига тебе вообще понадобились строки, заполненные пробелами? Если тебе нужно сравнивать структуры по memcmp, то заполни их нулями, а не пробелами. Тогда будет хотя бы совместимо с си-строками.
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
10.10.2020, 11:30
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ты не сможешь сделать реализацию методов в базовом классе, а переменные объявить в наследниках.
ну вообще-то могу.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class T>
class IDb2StringBase
{
  public:
  size_t Size() { return static_cast<T*>(this)->GetSize(); }  
    
  void clear()
  {
      memset(Ptr(), ' ', Size());
  }
  
  private:
  char*  Ptr()  { return static_cast<T*>(this)->GetPtr(); }         
};
это и называется CRTP.
1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.10.2020, 12:26  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ты не сможешь сделать реализацию методов в базовом классе, а переменные объявить в наследниках.
Как правильно сказал и показал GbaLog- могу (статический полиморфизм). Посмотри еще раз мое решение. Там переменные в наследниках, а их методы их обрабатывающие - в базовом.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.10.2020, 12:26
Помогаю со студенческими работами здесь

Как сделать свой интрепретатор C# или подключаемую из интерфейса DLL ?
Возможно я не совсем правильно обозвал эту тему, но смысл следующий. Есть программа работающая с сервером, получает и обрабатывает от...

Как сделать свой чат или сохранить файл на сервере ?
Как сделать так, чтобы программа могла сохранить файл на сервере сама ! Что-то вроди mkfile asdasd.txt ?

Как сделать чтобы каждое значение имело свой идентификатор или класс?
помогите пожалуйста ... у меня такая проблема .... есть часть кода, которая выводит значение таблицей (соответственно стиле я могу...

Как сделать чтобыСр.стоимость или спускалась на столько же строк или удалялась вообще?
у меня дано два столбца: название конфет стоимость степ 260 няша ...

Откуда Joomla 2.5х вытаскивает менюшки? Или как сделать многомерное меню через свой модуль
Здравствуйте форумчане! Под Жумлу пишу редко, поэтому при сюрйозных задачах приходиться биться о гранит мануалов) Честно говоря, задолбался...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru