LINUX.ORG.RU

Если охота всяких удобств, используй Ц++ и STL, а что-нть простенькое, просто на Ц (ибо Ц++, как известно, не трУЪъ и реальные пацаны это не юзают) можно написать и самому.

Deleted
()
Ответ на: комментарий от alphex_kaanoken

А зачем нужны одновременно sprintf и snprintf?

anonymous
()
Ответ на: комментарий от alphex_kaanoken

:)) Прости но меня это очень уж улыбнуло. Как ты представляешь себе что делает strlen() сейчас? Она ищет длину строки таким вот способом:

while (c != '\0') {
c = str[i];
i++;
}

И оптимизировать это никак нельзя. Скажем строку в 100 символов оно считает практически незаметно, но если делать это 5000 раз (например: массовое переименование файлов, парсинье mp3 тегов, листание директории, etc). Не проще ли:

return str.len;

Как бонус если правильно переписать функции в strings.h и string.h то buffer overflow станеть гораздо более редкой проблемой. Ну и все функции типа snprintf идут лесом.

Krechet
() автор топика

А зачем это в libc-то пихать?

Вообще библиотечных реализаций строк сколько угодно. Но libc тут не при чём.

Teak ★★★★★
()
Ответ на: комментарий от Krechet

> Как бонус если правильно переписать функции в strings.h и string.h то buffer overflow станеть гораздо более редкой проблемой. Ну и все функции типа snprintf идут лесом.

Лесом идут совместимость и быстродействие. Ты просто предлагаешь сделать glibc несовместимой со стандартами языка C, в результате чего ей абсолютно никто не станет пользоваться.

Просто пользуйся другим языком. Тебя ж никто не заставляет писать именно на C, правда?

Teak ★★★★★
()
Ответ на: комментарий от Krechet

> И оптимизировать это никак нельзя.

Почему?

> Скажем строку в 100 символов оно считает практически незаметно, но если делать это 5000 раз (например: массовое переименование файлов, парсинье mp3 тегов, листание директории, etc).

Так делайте правильно, в чем проблема?

Sorcerer ★★★★★
()
Ответ на: комментарий от Teak

А как же overloading? Пару версий glibc будут две версии каждой функции. Потом старое метится как depricated, потом obsolete. Процес уже давно отработан.

А про скорость - смотри мой пост выше. То как сделанно сейчас медленнее даже при ПУСТОЙ! строке чем если со структурой. Так что невижу пока аргументов кроме "а лень".

Krechet
() автор топика
Ответ на: комментарий от Sorcerer

Как почему? Потому что нельзя: ты что предлогаешь читать каждый четный символ и надеятся что длинна твоей строки нечетная?

Krechet
() автор топика
Ответ на: комментарий от Sorcerer

>Так делайте правильно, в чем проблема?

В том что надо делать повсеместно и сразу (e.g. POSIX).

Krechet
() автор топика
Ответ на: комментарий от Krechet

так

во первых пиши правильно алгоритмы чтобы не использовать это по много раз, во вторых напиши свою библиотеку или возьми готовую где это уже есть.

alphex_kaanoken ★★★
()

> Может и боян но... Так почему же никто так и не сделал нечто типа:

> в glibc? В чем загвоздка?

Потому что ты гонишь. ASCIIZ строки самодостаточны - а ты предлагаешь для строки сделать два разобщенных объекта - собственно, ту же самую ASCIIZ строку, и структуру непонятного назначения.

Используй C++/STL, как тебе уже указали - и не изобретай велосипед, оно того не стоит.

Spectr ★★★
()
Ответ на: комментарий от Krechet

Ты вообще в курсе что кроме Linux/glibc есть и другие платформы? И ты в курсе, сколько софта написано на C, который ради твоей прихоти никто переписывать не собирается?

Тебе зачем это именно в glibc-то пихать, расскажи?

Teak ★★★★★
()
Ответ на: комментарий от Krechet

> Как почему? Потому что нельзя: ты что предлогаешь

Я предлагаю предоставить такой алгоритм, который будет невозможно написать без многократного использования strlen и других "извращений" C. Это и будет являться доказательством утверждения, что "оптимизировать это никак нельзя".

Sorcerer ★★★★★
()
Ответ на: комментарий от Spectr

Тогда зачем интересно есть такие классы как int, long int, double, etc? Ведь они по сути 4 byte'а или там 8. 1 байт ведь самодостаточен.

В любом случае по моему ни у кого нет желания переписывать такие вещи как Linux kernel на С++. А прибавка скорость при копировании многих мелких файлов и листании директорий будет реальная. И как насчет баз данных?

Ну и еще: что ты думаешь есть String class в C++? Правильно! Объект "непонятного назначения" поверх ASCII строки.

И то что я предложил - не мой велосипед.

ЗЫ а можно ссылку/имя такой библиотеки?

Krechet
() автор топика
Ответ на: комментарий от Krechet

> Под ЭТО подразумевается strlen а не то что я с ним буду делать.

Ну так не используйте strlen, если не хотите. Или что-то этому мешает?

Sorcerer ★★★★★
()
Ответ на: комментарий от Krechet

> Тогда зачем интересно есть такие классы как int, long int, double, etc?

Хм... Ты явно что-то не то курил... Завязывай с такой травой.

> Ну и еще: что ты думаешь есть String class в C++? Правильно! Объект "непонятного назначения" поверх ASCII строки.

Вполне понятного, и притом, очень качественно написанный (по крайней мере, в нормальных либах - у GCC с этим все ок).

Spectr ★★★
()
Ответ на: комментарий от Spectr

Ну а я о чем? Я же и говорю что если в С++ есть такой класс то приведенная выше структура имеет право на жизнь.

Krechet
() автор топика
Ответ на: комментарий от Teak

>Я что-то не понял, а почему мне не отвечают? :)

Извени незаметил.

>Ты вообще в курсе что кроме Linux/glibc есть и другие платформы?

В курсе. И что?

>И ты в курсе, сколько софта написано на C, который ради твоей прихоти никто переписывать не собирается?

Так переписывать особо ничего не недо. Вплоть до того что можно сделать header file и прописать туда хитрый макрос. А прибавка в производительности получается бесплатная.

>Тебе зачем это именно в glibc-то пихать, расскажи?

Затем чтоб в итоге все делали этим способом и не чурались strlen. Чтоб в С все работало искаропки. Ну и чтоб когда это вкльючат в glibc все посмотрят с скажут: Кашерна!

Krechet
() автор топика
Ответ на: комментарий от Krechet

Хех, ну так попробуй напиши хитрый макрос, всунь его в string.h, а потом пересобери всю систему с ним Ж) (будет новый дистриб: SuperGentoo)
А где обратная совместимость, где?

Deleted
()

USE pascal

И вообще, может в этой строчке, завершенной 0 полгое собрание сочинений Ленина хранится, а ты хочешь урезать его до int.

anonymous
()
Ответ на: комментарий от anonymous

Pascal замечательный язык но С мне нравится больше. Ну а то что пересобирать систему так не волнуйтесь - за вас это сделает Патрик. А гентушники сами все все равно пересобирают при каждом апдейте glibc. Так что нет возражений/аргументов?

Krechet
() автор топика
Ответ на: комментарий от Krechet

>Так что нет возражений/аргументов?

А это тебе чем не возражение/аргумент?:

>И вообще, может в этой строчке, завершенной 0 полгое собрание сочинений Ленина хранится, а ты хочешь урезать его до int.

Ramen ★★★★
()
Ответ на: комментарий от Ramen

Это в локализированном варианте...

Krechet
() автор топика
Ответ на: комментарий от anonymous

>И вообще, может в этой строчке, завершенной 0 полгое собрание сочинений Ленина хранится, а ты хочешь урезать его до int.

А какого типа вообще указатели сами по себе, что они позволяют работать с традиционными строками, содержащими полное собрание сочинений Ленина? А как устроена работа с большими файлами (>4Gb)?

Допустим вот реализуют в glibc такую вещь, кто ее будет использовать? Будут все равно в основном использовать стандартные кроссплатформенные char* функции. И что-то мне кажется, что никакими хитрыми макросами тут подменить одно другим нельзя.

Deleted
()
Ответ на: комментарий от anonymous

Ну а как вот до всех остальных символов добраться, если уж int'а якобы не хватает?? Так что это не аргумент, а глупость полная.
Тем более, если вспомнить о том, что на реальных системах макс. размер виртуальной памяти доступной процессу ограничен (4гб или 2 на 32-битных?), так что сколь угодно длинной строки все равно быть не может.

Deleted
()
Ответ на: комментарий от Deleted

Чем 
struct string_new_standart {
   int len;
   char* str;
}

менее кросс платформенно char* str? А про макрос так все просто:

#define strlen     strlen_new_standart
#define printf     printf_new_standart
...
#define char*      string_new_standart*

усё? Можно правда не извращятса и написать шелловый скрипт 
который заменит все char* на string_new_standart*. 
Потом ставится новый glibc, Патрик тратит пару ночей на 
пересборку гент^Wслаки и всем наступает счастье.

Krechet
() автор топика
Ответ на: комментарий от Deleted

long long'а за глаза хватит. Или двух. А вообще по моему строка >4GB это гораздо менее кошерно чем то что сейчас творится в strings.h.

Krechet
() автор топика
Ответ на: комментарий от Krechet

Ага, а потом берем старый рабочий кусок кода.

char* str;
str = malloc(1024*sizeof(char));
fgets(str,1023,stdin);
printf("first character is: %c", str[0]);

и смотрим в какую кашу он превращается после таких макросов.

Т.е переопределять еще и придется способ доступа к такой строке, ибо str[0] уже не канает. Ц это не умеет, зато умеет Ц++ и... так это же получается stl!

Deleted
()
Ответ на: комментарий от Deleted

Подожди. А как насчет сделать:

string_new_standart* create_string() {

string_new_standart* sns = malloc(sizeof(string_new_standart));
   sns.len = 0;
   sns.str = malloc(sizeof(char));

   return sns;
}

Таким образом твой код превращяется в:

string_new_standart sns = create_string();
fgets_new_standart(sns, stdin);   

//длинну строки указывать больше не надо так как 
//fgets_new_standart сам все определит и динамически 
//увеличит выделенную память

printf("first character is: %c", sns.str[0]); 

доступ к str[0] теперь просто по sns.str[0] или по некой функции типа:

char get_char_in_string_new_standart(string_new_standart* sns, int i) {

   if (i >= sns.len) {
      error("out of bound error\n");
      return '\0';
   }
   else return sns.str[i];

}

Krechet
() автор топика
Ответ на: комментарий от Krechet

Как видишь такой подход очистит код, уберет головную боль о выделении памяти если fgets ждет 1023 символа, а получает 1024, ускорит некоторые процессы и уменьшит количество функцый в почти 2 раза. А про совместимость ныть не надо: API/ABI в glibc меняется с каждым релизом. Я еще раз утверждаю: тут нет ничего с чем не справился бы простой скриптик.

Krechet
() автор топика
Ответ на: комментарий от Krechet

Используй C++ и не делай с мозгами собеседников то, к чему предназначены совершенно другие органы.

Xellos ★★★★★
()
Ответ на: комментарий от Krechet

Вот! Подменить одно другим не удастся, можно лишь добавить новое к уже существующему и переписывать свой код при желании заюзать новые строки.
Но:
1) ради экономии на strlen, пошли усложнения других функций, что съест возможный прирост производительности.
2)ну и наконец это велосипед :) google -> fast string library -> одна из первых ссылок http://bstring.sourceforge.net/bstrFAQ.shtml

Deleted
()
Ответ на: комментарий от Deleted

Про библиотеки шас почитаю, но смысл вего этого не только в strlen но и в fgets, snprintf и т.д. Динамические строки это хорошо потому что не надо себе ипать моск всякими мыслями типа "а вдруг имя файла диннее чем 1023 char'а?".

Krechet
() автор топика
Ответ на: комментарий от Krechet

:) я рад :)
просто стандартные строки - самая простая библиотека, дающая самый полный контроль над тем что творится внутри, а у динамических строк есть своя фига в кармане...

пример, обычные строки:

char data[1024];
fgets(data, 512, stdin);
char* tmp 0;
tmp = find_first_appearence_of_symbol('a',data);
strcat(data, " something", 511);
if(tmp!=0)printf("print begin from 'a': %s",tmp);

тут все ок

а теперь:

newstr* data = create_newstr(); //динамическая память тормознее
newfgets(data,stdin);
char* tmp = find_first_appearence_of_symbol('a',data->str);
newstr* tmp2 = new_find_first_appearence_of_symbol('a',data); //копирование всей подстроки? или просто новый указатель на середину имеющегося буфера? а если модифицировать будем? нужен copy-on-write механизм - в любом случае overhead.
newstrcat(data,"something");
if(tmp!=0)printf("print begin from 'a': %s",tmp);
//Бухаха! Возможен segfault, ибо data могло реаллокнуться во время newstrcat


Deleted
()
Ответ на: комментарий от Deleted

в догонку:
if(tmp2!=0)new_printf("print begin from 'a': %s",tmp2);
результат совсем неочевиден и сильно зависит от деталей реализации.
упрощаем в одном - усложняем в другом.

Deleted
()
Ответ на: комментарий от Deleted

В первом примере та же проблема что и во втором:


tmp = find_first_appearence_of_symbol('a',data); 

Потом если ты модифицируешь tmp:

tmp[0] = 'b';

то data меняется тоже. И тот же copy-on-write нужен.


Во втором примере:

newstr* data = create_newstr(); //динамическая память тормознее

в данном случае разници в скорости практически не будет. Там один malloc а там два. Оба очень мелкие.


char* tmp = find_first_appearence_of_symbol('a',data->str); //это не надо следующая строка все сделает

newstr* tmp2 = new_find_first_appearence_of_symbol('a',data); //фактически tmp2->str = index(str, 'a') но если будем менять tmp2 
//то тогда часть data копируется в другое место в памяти и tmp2->str меняется

Для такого можно устроить например 

struct newstr {
   int len;
   char* str;
   int refcount; //количество структур ссылающихся на часть или весь str
   //меняется это значение по вызову new_index и иже с ними
}



Вместо

if(tmp!=0)printf("print begin from 'a': %s",tmp); 

делаем

if(tmp2->str!=0)new_printf("print begin from 'a': %s",tmp2); 

и получается что

strcat(data, " something", 511);
if(tmp!=0)printf("print begin from 'a': %s",tmp); 

и

newstrcat(data,"something");
if(tmp2->str!=0)new_printf("print begin from 'a': %s",tmp2);

одно и то же. Суть ведь не меняется потому что что то что то все равно в итоге обращается к tmp2->str что является char*.

Krechet
() автор топика
Ответ на: комментарий от Deleted

Опять же результат очевиден как я сказал выше:

s\tmp2!=0\tmp2->str!=0

Krechet
() автор топика
Ответ на: комментарий от Krechet

Что-то путанно ты написал, я так и не понял...
Вот придумал более наглядный пример.

Классика:
char data[1024] = "abcd";
char* tmp = index(data,'c');
strncat (data,"ef",10);
strcat (tmp,"gh",10);
printf(data); //выведет abcdefgh

New:
newstr* data = create("abcd");
newstr* tmp = find(data,'c');
newstrcat(data,"ef");
newstrcat(tmp,"gh");
printf(data);

подумаем как оно должно быть реализовано, чтобы получилось abcdefgh?
считая, в худшем случае, что при каждом newstrcat происходил realloc newstr->str?

Копировать весь str после во время find заранее не имеет смысла, ибо printf(data) уже точно не напечатает то что нам нужно.

Если реализован copy-on-write, то после find имеем tmp->str=*(data-
>str[2]), первый же realloc сменит data->str, а прежде занятую им память надо сохранять, дабы не сломать tmp->str, а потом все-таки освободить, причем включая первые две буковки, о которых tmp ничего не знает... Это первая проблема.
А во-вторых и в этом случае printf не напечатает то что нужно.

Усложняем структуру :)

struct newstr{
int len;
char* str; //указатель на начало нашей строки внутри strbuff->buff
smartchar* strbuff; //смарт-пойнтер для непосредственно строковых данных
}

struct smartchar{
int refcount;
char* buff; //данные, для них делается malloc и realloc
}

newstr* find(newstr* data, char ch){
newstr* ret = malloc(sizeof(newstr));
ret->strbuff = data->strbuff;
ret->strbuff->refcount++;
ret->str = index(data->strbuff->buff,ch);
return ret;
}

void newstrcat(newstr* dest, char* src){ //char* src для упрощения
char * tmp = malloc(dest->len+strlen(len));
strcat(tmp,dest->strbuff->buff);
strcat(tmp,src);
dest->strbuff->refcount--;
free(dest->strbuff->buff);
if(dest->strbuff->refcount == 0){
free(dest->strbuff);
}
dest->strbuff = malloc(sizeof(smartchar));
dest->strbuff->buff = tmp;
}


Весело получается?
Работает старая формула:
удобство*дуракоустойчивость*производительность = e^pi

Deleted
()
Ответ на: комментарий от Deleted

s/char * tmp = malloc(dest->len+strlen(len));/char * tmp = malloc(dest->len+strlen(src));/


И еще, не уверен, но когда используем
char str[1024]
никакого malloc не вызывается, память выделяется статически, а это гораздо быстрее.

Deleted
()
Ответ на: комментарий от Deleted

Ну во-первых

char data[1024] = "abcd";
char* tmp = index(data,'c');
strncat (data,"ef",10);
strcat (tmp,"gh",10);
printf(data); //выведет abcdefgh

это как раз и есть пример того чего делать не стоит (см. выше о плохих алгоритмах). Просто потому что так можно не значит что это хороший способ. Ни в одном другом широко распостроненном языке (включая C++) ты так не сделаешь потому что там строка это строка, а не область памяти. И я думаю не ничего что останавливает С наконец вылезти из каменного века в этом вопросе.

>Весело получается?

Получается не плохо. Могло бы быть и хуже. Учти что от програмиста все это будет спрятанно - он видит только удобство подхода где не не надо забивать себе на каждом шагу голову вопросами о том что будет со строкой которая не помещается в n бит. А написать этот код надо всего один раз (или взять из одной из библиотек по ссылке которую ты привел выше).

>Работает старая формула:
>удобство*дуракоустойчивость*производительность = e^pi

Удобство возрастает - благодоря более простой системе теперь не надо задумыватся о всей этой фигне с malloc-ами когда работаешь со вторым самым популярным типом данных. Не надо морочить себе мозги вопросами типа "а какая максимальная длина имени файла?" (приведи кастати элегантное решение этой проблемы используя char*).

Дуракоустойчивость возрастает - нет больше понятия buffer overflow со строками.

Производительность возрастает за счет функции strlen и всех функций которые ее используют: strcat, printf, etc.

Короче значение pi меняется. Ж)

Krechet
() автор топика
Ответ на: комментарий от Deleted

>И еще, не уверен, но когда используем >char str[1024] >никакого malloc не вызывается, память выделяется статически, а это гораздо быстрее.

Может быть но не в char* str = malloc(1024*sizeof(char));

Krechet
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.