- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
char *cat2(char *str1, char *str2)
{
int len;
char *ret;
/* malloc new string */
len = strlen(str1) + strlen(str2) + 1;
ret = (char *) malloc(len*sizeof(char));
/* copy the strings */
strcpy(ret, str1);
strcat(ret, str2);
/* free old strings */
free(str1);
free(str2);
return ret;
}
char *cat3(char *str1, char *str2, char *str3)
{
return cat2(cat2(str1, str2), str3);
}
char *cat4(char *str1, char *str2, char *str3, char *str4)
{
return cat2(cat2(str1, str2), cat2(str3, str4));
}
char *cat5(char *str1, char *str2, char *str3, char *str4,
char *str5)
{
return cat3(cat2(str1, str2), cat2(str3, str4), str5);
}
char *cat6(char *str1, char *str2, char *str3, char *str4,
char *str5, char *str6)
{
return cat3(cat2(str1, str2), cat2(str3, str4), cat2(str5, str6));
}
char *cat7(char *str1, char *str2, char *str3, char *str4,
char *str5, char *str6, char *str7)
{
return cat4(cat2(str1, str2), cat2(str3, str4), cat2(str5, str6), str7);
}
char *cat8(char *str1, char *str2, char *str3, char *str4,
char *str5, char *str6, char *str7, char *str8)
{
return cat4(cat2(str1, str2), cat2(str3, str4),
cat2(str5, str6), cat2(str7, str8));
}
char *cat9(char *str1, char *str2, char *str3, char *str4,
char *str5, char *str6, char *str7, char *str8,
char *str9)
{
return cat5(cat2(str1, str2), cat2(str3, str4), cat2(str5, str6),
cat2(str7, str8), str9);
}
Antervis 01.09.2017 05:36 # −1
bormand 01.09.2017 07:44 # +1
inkanus-gray 01.09.2017 12:08 # 0
roman-kashitsyn 01.09.2017 12:26 # 0
bormand 02.09.2017 17:19 # +7
Ты его уже и там и там закоммитить успел?
roman-kashitsyn 02.09.2017 23:30 # +2
Когда я говорю, что моноиды повсюду, я именно это имею ввиду
Antervis 01.09.2017 10:19 # +1
решена* - + / + ... / accumulate
roman-kashitsyn 01.09.2017 11:56 # +1
inkanus-gray 01.09.2017 12:18 # 0
А вообще у сишечки функции для строк запутанные. Ну вот зачем функция возвращает значение одного из аргументов?
j123123 02.09.2017 11:57 # +1
И вот типа тут вызывается cat2 который нам тут блядь аллоцирует массив размером в две строки, копирует две строки в него, освобождает память тех двух строк, ну а потом опять вызывается cat2 который ту же питушню делает. Царь разумеется выделил бы в cat3 память сразу под сумму размеров трех строк, и туда б эти три говностроки закопировали бы. А не вызывал бы cat2 два раза.
НО Царь бы не стал использовать заедушно-анскильные сишные говнонультерминированные строки, а сделал бы паскалеподобные строки, потому как тогда можно четко и дерзко memcpy делать, а не анскилльно выяснять место нулевого байтика и потом копировать
Antervis 02.09.2017 14:55 # −1
МС цари придумали говнонедонультерминированные строки, они называются bstr и они говно потому что нет никакого способа воспользоваться bstr не выделяя память в куче и не прибегая к небезопасным костыльным хакам
bormand 02.09.2017 15:42 # 0
Antervis 02.09.2017 16:30 # +1
получится. Я это и имел в виду под "небезопасными костыльными хаками".
И есть нюанс: компилятор вправе оптимизировать поле _size. А volatile использовать нельзя, т.к. это нарушает требования к constexpr
Макроснёй даже проще.
inkanus-gray 02.09.2017 16:01 # 0
Antervis 02.09.2017 16:51 # +3
1. кодировка по умолчанию - utf-8. Раздельные методы length (число символьных позиций) и size (размер в байтах). Явное указание кодировки в стандарте необходимо, иначе MS в своей реализации засунут туда локальную кодировку и сделают класс неюзабельным.
2. sso, cow оптимизации
3. API примерно как у QString, но с некоторыми изменениями:
а. отсутствие дублирования, например: с empty(), но без isEmpty()
б. преобразования кодировок - внешними параметризуемыми функциями
в. две версии split - одна "засовывает" разбитые строки в существующий контейнер строк (vector<string> v; s.split('\n', v);) или возвращающий контейнер указанного типа (s.split<list>() -> list<string>)
4. constexpr - конструкторы и базовые операции типа конкатенации (этого даже в с++17 для коротких строк не сделаешь)
5. полностью параметризуемые числовые преобразования to/from для (хотя бы) числовых типов ("полностью" значит и система исчисления, и ширина позиции, и точность, и числоденежнолокальный формат)
6. наличие соответствующего string_view со всеми аналогичными методами
Сдается мне, таких строк нет ни в одном яп. А жаль.
Antervis 02.09.2017 17:01 # 0
123123123 02.09.2017 19:22 # 0
ненужно
> QString
ненужно
> s.split<list>()
ненужно
> constexpr
ненужно
> числовые преобразования to/from
ненужно
Antervis 02.09.2017 19:49 # 0
123123123 02.09.2017 21:00 # 0
Antervis 02.09.2017 21:08 # 0
123123123 02.09.2017 21:38 # 0
Antervis 02.09.2017 23:35 # 0
http://franklinchen.com/blog/2011/12/08/revisiting-knuth-and-mcilroys-word-count-programs/
subaru 02.09.2017 23:53 # +1
И да, если при проектировании апи ты руководствуешься желанием писать наколеночные говнопарсеры, то ты делаешь это неправильно, как говорится.
Antervis 03.09.2017 14:23 # 0
123123123 03.09.2017 14:44 # +2
Лол, нет. Строки - это строки, а парсеры - это парсеры, не надо их лепить в одну кучу.
Насчет утилит для работы со строками: я нигде не говорил, что они ненужны. Мне не понравились твои конкретные идеи (которые процитировал). Заметь, я назвал ненужным только один из двух предложенных тобой сплитов.
roman-kashitsyn 02.09.2017 23:28 # +2
Итерация по символам где? Разбиение по словам и предложениям тоже неплохо иметь. Размера надо три: длину в байтах, в код поинтах и в графических символах.
> возвращающий контейнер указанного типа (s.split<list>() -> list<string>)
И зачем? Нужна ровно одна версия — которая range возвращает.
> cow оптимизации
Вот только не надо опять этот шлак тащить
Кмк, нужны только годные классы с честными именами bytes и bytes_view, которые не притворяются строками (у них всё равно плохо получается). Они только управляют временем жизни и предоставляю апи для работы с байтами.
Декодинг/подсчёт кодпоинтов/итерация и т.п. должны быть внешними функциями и возвращать ranges, которые можно засунуть в любой контейнер.
Antervis 03.09.2017 10:17 # −3
Я предлагаю в кодпоинтах. Для utf-8 это то же, что и в байтах. Обычно взять длину utf16 в байтах надо редко и для байтоебли, которую бы по возможности обойти. На крайняк на sizeof домножить
с ranges интереснее. Если глянуть ranges v3, то для какого-нибудь (s1+s2) | split('\n') нужно будет делать to_vector/to_list. Вообще штука хорошая, но имо, с ucs была бы намного приятнее.
Для строк нужно много того, чего не надо в других контейнерах. Те же кодпоинты например. Поэтому лучше пусть строки будут отдельно.
Моя б воля, я б вообще malloc/free и всю другую аллокационную дрянь свел в вектор байт. Что - то типа bytes(a,15) = bytes(b, 15, 7) - скопировать 15 байт из b со смещением 7 в a
roman-kashitsyn 03.09.2017 13:01 # +3
Я вообще не понимаю, что ты имеешь в виду. Длина в байтах нужна всегда, определённо. Длина в кодпоинтах это совсем другое — сколько кодпоинтов можно декодировать из байтов (это тоже самое только для ASCII).
Третья длина — эта ширина строки в символах. Это не тоже самое, что ширина в кодпоинтах. Без нормализации диакритические знаки могут давать дополнительные кодпоинты, но при отрисовке всё сливается в один символ. Есть символы-пробелы нулевой ширины, а уж про хитрости арабского я вообще молчу, ибо знаком с темой очень поверхностно и могу только представить масштаб проблемы. Эмодзи — это отдельная боль, несколько значков эмодзи могут объединяться, образуя новый значок.
Всё становится совсем интересным, когда в строке смешиваются left-to-right и right-to-left.
Antervis 03.09.2017 13:55 # −2
subaru 03.09.2017 14:08 # 0
inkanus-gray 03.09.2017 15:47 # +1
1. Символ «F» в UTF-8 кодируется одним байтом, символ «Щ» — двумя. Чему равен размер кодпоинта?
2. Символы «F» и «Щ» в UTF-16 кодируются двумя байтами, некоторые китайские иероглифы — двумя парами, т. е. четырьмя байтами (google: суррогаты). Чему равен размер кодпоинта?
3. Символ «ё» можно записать одним кодом, а можно двумя: «е» + надстрочный акцент, состоящий из двух точек. Чему равен размер кодпоинта в обоих случаях?
4. Код «fi» имеет семантическое значение, как у сочетания букв «f» + «i».
Чтобы не запутаться, нам придётся разделить кодирование (байтовое представление типа UTF-8, UTF-16, UCS-2, UCS-4 etc.), графическое представление (количество знакомест, например) и семантику (эквивалентность сочетаний букв и сочетаний кодов).
123123123 03.09.2017 16:52 # +1
Antervis 03.09.2017 17:46 # 0
inkanus-gray 03.09.2017 18:04 # 0
bormand 03.09.2017 16:21 # +3
defecate-plusplus 04.09.2017 02:09 # +5
вон в компании эппл, например, считают, что буква й после нормализации (normalized to Apple-modifiedᵍᵃʸ variant of Unicodeᵀᴹ Normalization Format D) должна записаться в двух кодпойнтах "и"+"крышечка", и ниибёт
inkanus-gray 04.09.2017 02:21 # +3
roman-kashitsyn 04.09.2017 11:21 # +2
Я как-то видел CSV файл с арабскими строками. Это вынос мозга.
Antervis 03.09.2017 17:49 # −1
> Кмк, нужны только годные классы с честными именами bytes и bytes_view, которые не притворяются строками (у них всё равно плохо получается). Они только управляют временем жизни и предоставляю апи для работы с байтами.
> Декодинг/подсчёт кодпоинтов/итерация и т.п. должны быть внешними функциями и возвращать ranges, которые можно засунуть в любой контейнер.
Всё это можно вылечить через uniform call syntax.
j123123 04.09.2017 04:51 # +3
На мой взгляд, идеальной строковой реализации нет и быть не может. Может быть строковая реализация, хорошо подходящая под некие конкретные требования. Цари вообще никакими строками с кодировками пользоваться не будут, они сделают себе структуру под массив как в поцкале:
и будут делать realloc, malloc и прочую хуиту руками, т.е. если царю надо где-то сконкатенировать семь таких строк, он может написать код, который вот берет от всех этих семи штук lenght, складывает, потом realloc-нуть первую строку по данному размеру и туда отmemcpy-ить все прочие, ну а если например царю надо будет много где в коде сшивать 7 строк в одну, царь, так уж и быть напишет функцию strcat7(struct tzar_str **a1, struct tzar_str *a2, ...) . И еще царь может накодогенерировать таких функций какие ему нужны для конкатенации нужных строк. Строка ведь по-сути это массив сраных байтов, нахера нужны эти ваши кривые абстракции со всякой херней?
Antervis 04.09.2017 05:53 # 0
kipar 04.09.2017 10:39 # +1
inkanus-gray 04.09.2017 13:06 # +1
1. В функциях регистронезависимого сравнения и поиска, в функциях изменения регистра — везде, где нужно определять/изменять регистр.
2. В функциях определения длины в знакоместах или в пикселях — там, где требуется информация о глифах, связанных с каждым символом.
3. В функциях вывода в консоль/гуй/файл, чтобы вывести поток в требуемой кодировке, а не Àíîíèìíûå.
4. В функциях определения длины в графических символах, в функциях вырезания фрагмента по графическим символам (вообще в функциях парсинга) — везде, где нужен доступ к графическому/семантическому символу, если кодировка переменной разрядности (как UTF-8).
*****
А теперь попробуем разделить на уровни:
1. Уровень хранилища. Строка — это просто цепочка байтов (пофигу в какой кодировке). Доступны функции выделения памяти, конкатенации, определения размера в байтах. Возможно, даже функции вывода (если предварительно чем-нибудь готовить нужную кодировку).
2. Уровень «зожатия». На этом уровне строка — это не просто цепочка байтов, а уже цепочка символов (но мы не знаем, на каком языке текст). В этот уровень заложен алгоритм упаковки кодпоинтов в байты, например, UTF-8, UTF-16 etc. На этом уровне доступны функции определения длины в кодпоинтах, функции вырезания фрагмента по номеру кодпоинта, функции чёткого поиска (поиск будет по кодпоинту, а не по символу) и сравнения.
3. Уровень символов. Строка на этом уровне — это цепочка конкретных известных символов. На этом уровне должна быть известна кодировка. На этом уровне доступны все функции парсинга (нечёткий поиск и нечёткое сравнение, например, регистронезависимое), функции изменения регистра, функции определения длины в знакоместах или в графических символах (да в чём угодно).
Третий уровень вообще может быть отдельной библиотекой.
Antervis 04.09.2017 14:02 # +1
Моя идея: вот есть у нас набор классов codepage, с определенным набором методов, поведение которых зависит от кодировки. Например, преобразования регистра, поиск, преобразования кодировки - не принципиально. Есть дефолтный вариант:
using string = basic_string<char, codepage_utf8, allocator<...>>;
Скажем, для utf16:
using string_utf16 = basic_string<wchar_t, codepage_utf16, allocator<...>>;
Тогда преобразование кодировки:
string_utf16 s1 = u"какая-нибудь строчка";
string s2 = s1; // здесь вызовется какой-нибудь codepage_utf16::convert<codepage_utf8>(. ..);
Тогда а: добавление поддержки кодировки это всего лишь добавление библиотечного codepage_... класса
б. внутри яп кодировки уже не перепутаешь
roman-kashitsyn 04.09.2017 14:07 # +1
Объекты кодировок нужны (и это уже реализовано в java, к примеру), а вот совать их в строки — сомнительная идея. Кмк, лучше, если все строки внутри языка в одной кодировке, а альтернативные кодировки используются для ввода/вывода.
Antervis 04.09.2017 14:09 # +1
bormand 04.09.2017 07:33 # +1
Плюсану. Имхо, все функции типа сравнений, поиска, нормализации, сплитов и т.п. должны быть внешними, а не торчать из строки.
roman-kashitsyn 04.09.2017 11:20 # 0
>> Кмк, нужны только годные классы с честными именами bytes и bytes_view, которые не притворяются строками
>> Декодинг/подсчёт кодпоинтов/итерация и т.п. должны быть внешними функциями
Ну вот, нас уже трое. Осталось убедить комитетъ.
Antervis 04.09.2017 14:15 # 0
Что до внешних/внутренних функций - тут я надеюсь на uniform call syntax. С одной стороны, у строки нет метода (скажем) string::split(regexp r), зато в модуле/библиотеке regexp есть метод split(string &s, regexp r). И тогда можно писать return s.split(regexp("\d{1,}")).filter(regexp( "{*}")).join('\n');
roman-kashitsyn 04.09.2017 14:39 # 0
Напиши обёртку, которая возвращает строку в utf8.
> тут я надеюсь на uniform call syntax.
Это всё свистоперделки, сути не меняет.