1. Если уж пишешь на C, то нужно понимать его ... суть. А суть такая что это почти ассемблер по своей идеологии. А так как всем охота иметь строки произвольной длинны, и ни один нормальный человек не будет передавать через стек (а именно через стек и возвращаются все результаты работы функций) кусок данных потенциально бесконечного размера, ну или просто достаточно крупного размера. Поэтому в C, функции не возвращают строки! На крайняк они возвращают УКАЗАТЕЛИ на строки. ( char и char* это как-бе разные вещи )
2. А как-же работают все строковые функции? Есть два метода, либо они сами выделяют память, шаманят в ней, а потом возвращают указатель char* на выделенный блок ( но это как-бе нестандартный для C подход ). Второй метод подразумевает что вы САМИ выделили кусок динамической памяти для строки, запомнили адрес этого куска в типизированном указателе char* ( то есть типа строку создали ) и передаёте этот указатель в строковую функцию, которая через указатель лезет в выделенный вами блок памяти и делает с ним разные интимные вещи.
То есть, если говорить о способах реализации и использования строковых функций в C, то :
А. Есть общепринятый велосипед с передачей в функцию указателя на уже инициализированную строку
Б. Есть другие велосипеды, реже используемые, с квадратными колёсами, но работоспособные
P.S. И да, в C++ можно возвращать из функции строки, не парясь с выделением памяти и указателями. Эти возможности реализуются либо стандартной библиотекой языка C++, либо сторонними библиотеками, из которых я могу назвать Qt, boost
P.P.S. И да, C и C++ это разные языки
Нужна функция типа format в Delphi/Builder, чтобы возвращала строку
есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),
а нужно чтобы вернула результирующую строку,
можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров
Здравствуйте, MASReady, Вы писали:
MAS>можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров
придется разобраться
Re[4]: нужен аналог функции format в Delphi/Builder
Здравствуйте, SaZ, Вы писали:
SaZ>Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.
Спасибо брат, я как раз подбирался к этому, но не успел
Скажи где познакомиться с возможными последствиями возврата указателей на локальные переменные.
Переменная будет скопирована и уничтожена сразу после возвращения, какой может быть здесь криминал?
Re[5]: нужен аналог функции format в Delphi/Builder
Здравствуйте, MASReady, Вы писали:
MAS>почитал про возврат ссылок (или указателей) на локальные переменные MAS>но у тебя в коде my_vsnprintf возвращается ссылка не на локальную переменнную, а на полученную во входных параметрах, где здесь может быть проблема?
Я так написал, чтобы не говнокодить писать неудобный код. Вообще, как писали ранее, vsnprintf должна полностью делать то, что тебе нужно. А ещё лучше использовать std::string и прочие, чтобы не городить велосипедов.
Здравствуйте, MASReady, Вы писали:
MAS>Пишу под Linux на KDevelop
MAS>Нужна функция типа format в Delphi/Builder, чтобы возвращала строку
MAS>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку), MAS>а нужно чтобы вернула результирующую строку, MAS>можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров
MAS>вопчем ПАМАГИТЕ
А почему тема Delphi/Builder в ветке C/C++??????????????
Re[2]: нужен аналог функции format в Delphi/Builder
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, MASReady, Вы писали:
MAS>>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),
ДД>есть vsprintf().
vsprintf тоже int возвращает, а не строку
int vsprintf (char * str, const char * format, va_list arg );
Re[2]: нужен аналог функции format в Delphi/Builder
Здравствуйте, MASReady, Вы писали:
MAS>vsprintf тоже int возвращает, а не строку MAS>int vsprintf (char * str, const char * format, va_list arg );
Строку он кладет в char * str. Поэтому, кстати, настоятельно рекомендуется использовать vsnprintf(), чтобы не произошло переполнения буфера.
В GNU C library есть еще vasprintf(), которая сама распределяет память для строки.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, MASReady, Вы писали:
MAS>Пишу под Linux на KDevelop
MAS>Нужна функция типа format в Delphi/Builder, чтобы возвращала строку
MAS>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку), MAS>а нужно чтобы вернула результирующую строку, MAS>можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров
MAS>вопчем ПАМАГИТЕ
Здравствуйте, MASReady, Вы писали:
MAS>можно сделать при помощи boost::format, QString и иже с ними, но это сильно все усложняет
MAS>нужна простая C-шная реализация
Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.
Здравствуйте, SaZ, Вы писали:
SaZ>Здравствуйте, MASReady, Вы писали:
MAS>>можно сделать при помощи boost::format, QString и иже с ними, но это сильно все усложняет
MAS>>нужна простая C-шная реализация
SaZ>Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.
SaZ>
почитал про возврат ссылок (или указателей) на локальные переменные
но у тебя в коде my_vsnprintf возвращается ссылка не на локальную переменнную, а на полученную во входных параметрах, где здесь может быть проблема?
Re[5]: нужен аналог функции format в Delphi/Builder
MAS>Спасибо брат, я как раз подбирался к этому, но не успел MAS>Скажи где познакомиться с возможными последствиями возврата указателей на локальные переменные. MAS>Переменная будет скопирована и уничтожена сразу после возвращения, какой может быть здесь криминал?
Локальные переменные выделяются на стеке и после выхода из функции или метода класса там может даже что-то другое оказаться. Особенно, если по дороге где-то неявно еще были вызовы функций (умные указатели, перегруженные операторы и т.п.)
В принципе можно даже segfault словить.
Re[2]: нужен аналог функции format в Delphi/Builder
Здравствуйте, dmitryalexeeff, Вы писали:
D>1. Если уж пишешь на C, то нужно понимать его ... суть. А суть такая что это почти ассемблер по своей идеологии. А так как всем охота иметь строки произвольной длинны, и ни один нормальный человек не будет передавать через стек (а именно через стек и возвращаются все результаты работы функций) кусок данных потенциально бесконечного размера, ну или просто достаточно крупного размера. Поэтому в C, функции не возвращают строки! На крайняк они возвращают УКАЗАТЕЛИ на строки. ( char и char* это как-бе разные вещи ) D>2. А как-же работают все строковые функции? Есть два метода, либо они сами выделяют память, шаманят в ней, а потом возвращают указатель char* на выделенный блок ( но это как-бе нестандартный для C подход ). Второй метод подразумевает что вы САМИ выделили кусок динамической памяти для строки, запомнили адрес этого куска в типизированном указателе char* ( то есть типа строку создали ) и передаёте этот указатель в строковую функцию, которая через указатель лезет в выделенный вами блок памяти и делает с ним разные интимные вещи.
D>То есть, если говорить о способах реализации и использования строковых функций в C, то : D>А. Есть общепринятый велосипед с передачей в функцию указателя на уже инициализированную строку D>Б. Есть другие велосипеды, реже используемые, с квадратными колёсами, но работоспособные
D>P.S. И да, в C++ можно возвращать из функции строки, не парясь с выделением памяти и указателями. Эти возможности реализуются либо стандартной библиотекой языка C++, либо сторонними библиотеками, из которых я могу назвать Qt, boost D>P.P.S. И да, C и C++ это разные языки
это все понятно,
я про то что:
//создаем переменную - указатель:char *str;
//вызываем функцию которой в качестве параметра эту переменную и передаем
//она с ним шаманит(выделяет для него память и пишет в него чего-нить)
//и её же и возвращает:
savetolog(my_fmtstr(str,fmt,"разные переменные указанные в строке формата %s,%d,...."));
//ну и сразу чистим переменную
free(str);
...
//функция примерно как нарисовал уважаемый SaZchar * my_fmtstr( char *result, const char *fmt, ... )
{
va_list args;
va_start( args, fmt);
int size=vsnprintf( result, 0, fmt, args );
//va_end(args); //в man написано, после каждого вызова va_start писать va_end,
//интересно, в данной реализации функции , т.е. если несколько раз вызываю va_start,
//можно ли только один раз в конце написать va_end, т.к. va_start вызывается 2 раза
//или таки второй раз создавать еще одну переменную типа va_list и писать для нее va_start ... va_end
//вопчем так как сейчас стабильно работаетif (size<0) return NULL;
va_start( args, fmt);
result=(char*)malloc(size+1);
size=vsnprintf( result, size+1, fmt, args );
va_end(args);
if (size<0) return NULL;
return result;
}
Re[3]: нужен аналог функции format в Delphi/Builder
MAS> char *str;
MAS>//вызываем функцию которой в качестве параметра эту переменную и передаем
MAS>//она с ним шаманит(выделяет для него память и пишет в него чего-нить)
MAS>//и её же и возвращает:
MAS> savetolog(my_fmtstr(str,fmt,"разные переменные указанные в строке формата %s,%d,...."));
MAS>//ну и сразу чистим переменную
MAS> free(str);
MAS>...
MAS>//функция примерно как нарисовал уважаемый SaZ
MAS>char * my_fmtstr( char *result, const char *fmt, ... )
MAS>{
MAS> va_list args;
MAS> va_start( args, fmt);
MAS> int size=vsnprintf( result, 0, fmt, args );
MAS> //va_end(args); //в man написано, после каждого вызова va_start писать va_end,
MAS> //интересно, в данной реализации функции , т.е. если несколько раз вызываю va_start,
MAS> //можно ли только один раз в конце написать va_end, т.к. va_start вызывается 2 раза
MAS> //или таки второй раз создавать еще одну переменную типа va_list и писать для нее va_start ... va_end
MAS> //вопчем так как сейчас стабильно работает
MAS> if (size<0) return NULL;
MAS> va_start( args, fmt);
MAS> result=(char*)malloc(size+1);
MAS> size=vsnprintf( result, size+1, fmt, args );
MAS> va_end(args);
MAS> if (size<0) return NULL;
MAS> return result;
MAS>}
MAS>
Красиво получилось
Но это нестандартный подход немного, что не мешает ему быть работоспособным.
Кстати, работал я с одной платной либой по распознаванию отпечатков пальцев. Так вот в ней, как раз использовали этот путь — выделяли память внутри своих функций. Только по итогу в API всё равно была куча мест, куда было нужно передавать указатель на инициализированную область памяти. Поэтому при вызове функций было недостаточно посмотреть на их сигнатуру и название. Почти по каждой функции нужно было читать доки, чтобы понять, где нужен инициализированный указатель, а где сырой
Re[4]: нужен аналог функции format в Delphi/Builder
Вот что получилось в итоге, мож кому пригодится, главное не забыть когда строка станет ненужной сделать ей free
может и не супер стильно зато стабильно и удобно!!!
char * format(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
char * result=NULL;
int res=vsnprintf(result, 0, fmt, args);
if (res>0) {
int i;
for(i=0;i<glErrorRetryCount;i++) if ((result=(char*)malloc(res+1))!=NULL) break;
if (i==glErrorRetryCount) {result=NULL;return result;};
va_start(args, fmt);
res=vsnprintf(result, res+1, fmt, args);
}
return result;
};
Re[5]: нужен аналог функции format в Delphi/Builder