нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 12.09.11 13:00
Оценка: :))
Пишу под Linux на KDevelop

Нужна функция типа format в Delphi/Builder, чтобы возвращала строку

есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),
а нужно чтобы вернула результирующую строку,
можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров

вопчем ПАМАГИТЕ

27.10.11 17:13: Перенесено из 'C/C++'
delphi format linux c++ sprintf
Re: нужен аналог функции format в Delphi/Builder
От: ZegSoft Россия  
Дата: 12.09.11 13:08
Оценка:
Здравствуйте, 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  
Дата: 12.09.11 13:13
Оценка:
ZS>А почему тема Delphi/Builder в ветке C/C++??????????????

потому что MAS>>Пишу на c/c++ под Linux на KDevelop
читаем вопрос внимательней
Re: нужен аналог функции format в Delphi/Builder
От: ДимДимыч Украина http://klug.org.ua
Дата: 12.09.11 13:38
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),


есть vsprintf().
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[2]: нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 12.09.11 14:25
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>Здравствуйте, MASReady, Вы писали:


MAS>>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),


ДД>есть vsprintf().


vsprintf тоже int возвращает, а не строку
int vsprintf (char * str, const char * format, va_list arg );
Re: нужен аналог функции format в Delphi/Builder
От: uzhas Ниоткуда  
Дата: 12.09.11 14:46
Оценка: +1
Здравствуйте, MASReady, Вы писали:

MAS>можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров

придется разобраться
Re[2]: нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 12.09.11 15:03
Оценка:
можно сделать при помощи boost::format, QString и иже с ними, но это сильно все усложняет

нужна простая C-шная реализация
Re[3]: нужен аналог функции format в Delphi/Builder
От: ДимДимыч Украина http://klug.org.ua
Дата: 12.09.11 15:11
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>vsprintf тоже int возвращает, а не строку

MAS>int vsprintf (char * str, const char * format, va_list arg );

Строку он кладет в char * str. Поэтому, кстати, настоятельно рекомендуется использовать vsnprintf(), чтобы не произошло переполнения буфера.
В GNU C library есть еще vasprintf(), которая сама распределяет память для строки.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: нужен аналог функции format в Delphi/Builder
От: Ops Россия  
Дата: 12.09.11 15:43
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>Пишу под Linux на KDevelop


MAS>Нужна функция типа format в Delphi/Builder, чтобы возвращала строку


MAS>есть sprintf, но она возвращает int(кол-во символов в результате или ошибку),

MAS>а нужно чтобы вернула результирующую строку,
MAS>можно написать обертку, для sprintf, но я не очень разбираюсь с функциями с неопределенным количеством параметров

MAS>вопчем ПАМАГИТЕ


А обязательно нужна функция, и именно C-style?
Потому что можно например так: http://www.rsdn.ru/forum/cpp/4074684.1.aspx
Автор: remark
Дата: 11.12.10
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: нужен аналог функции format в Delphi/Builder
От: SaZ  
Дата: 12.09.11 15:51
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>можно сделать при помощи boost::format, QString и иже с ними, но это сильно все усложняет


MAS>нужна простая C-шная реализация


Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.

#include <stdio.h>
#include <stdarg.h>

char * my_vsnprintf( char *result, int size, const char *fmt, ... )
{
  va_list args;
  va_start( args, fmt);

  vsnprintf( result, size, fmt, args );

  return result;
}

int main( void )
{
  char *szWord1 = "Preved";
  char *szWord2 = "medved";

  const int cBufSize = 100;
  char szBuffer[ cBufSize ];
  char *output;

  output = my_vsnprintf( szBuffer, cBufSize, "%s %s!", szWord1, szWord2 );
  printf( "%s", output );

  http://codepad.org/xUrvDaKu

  return 0;
}
Re[4]: нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 12.09.11 18:55
Оценка: :)
Здравствуйте, SaZ, Вы писали:

SaZ>Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.



Спасибо брат, я как раз подбирался к этому, но не успел
Скажи где познакомиться с возможными последствиями возврата указателей на локальные переменные.
Переменная будет скопирована и уничтожена сразу после возвращения, какой может быть здесь криминал?
Re[4]: нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 13.09.11 09:04
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, MASReady, Вы писали:


MAS>>можно сделать при помощи boost::format, QString и иже с ними, но это сильно все усложняет


MAS>>нужна простая C-шная реализация


SaZ>Настоятельно рекомендую так не делать. Перед употреблением познакомиться с возможными последствиями возврата указателей на локальные переменные.


SaZ>
SaZ>#include <stdio.h>
SaZ>#include <stdarg.h>

SaZ>char * my_vsnprintf( char *result, int size, const char *fmt, ... )
SaZ>{
SaZ>  va_list args;
SaZ>  va_start( args, fmt);

SaZ>  vsnprintf( result, size, fmt, args );

SaZ>  return result;
SaZ>}

SaZ>int main( void )
SaZ>{
SaZ>  char *szWord1 = "Preved";
SaZ>  char *szWord2 = "medved";

SaZ>  const int cBufSize = 100;
SaZ>  char szBuffer[ cBufSize ];
SaZ>  char *output;

SaZ>  output = my_vsnprintf( szBuffer, cBufSize, "%s %s!", szWord1, szWord2 );
SaZ>  printf( "%s", output );

SaZ>  http://codepad.org/xUrvDaKu

SaZ>  return 0;
SaZ>}

SaZ>


почитал про возврат ссылок (или указателей) на локальные переменные
но у тебя в коде my_vsnprintf возвращается ссылка не на локальную переменнную, а на полученную во входных параметрах, где здесь может быть проблема?
Re[5]: нужен аналог функции format в Delphi/Builder
От: SaZ  
Дата: 13.09.11 09:57
Оценка: +1
Здравствуйте, MASReady, Вы писали:

MAS>почитал про возврат ссылок (или указателей) на локальные переменные

MAS>но у тебя в коде my_vsnprintf возвращается ссылка не на локальную переменнную, а на полученную во входных параметрах, где здесь может быть проблема?

Я так написал, чтобы не говнокодить писать неудобный код. Вообще, как писали ранее, vsnprintf должна полностью делать то, что тебе нужно. А ещё лучше использовать std::string и прочие, чтобы не городить велосипедов.
Re[5]: нужен аналог функции format в Delphi/Builder
От: Michael7 Россия  
Дата: 13.09.11 20:02
Оценка:
Здравствуйте, MASReady, Вы писали:


MAS>Спасибо брат, я как раз подбирался к этому, но не успел

MAS>Скажи где познакомиться с возможными последствиями возврата указателей на локальные переменные.
MAS>Переменная будет скопирована и уничтожена сразу после возвращения, какой может быть здесь криминал?

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

В принципе можно даже segfault словить.
Re: нужен аналог функции format в Delphi/Builder
От: dmitryalexeeff  
Дата: 14.09.11 02:08
Оценка: 1 (1) -1 :)
1. Если уж пишешь на C, то нужно понимать его ... суть. А суть такая что это почти ассемблер по своей идеологии. А так как всем охота иметь строки произвольной длинны, и ни один нормальный человек не будет передавать через стек (а именно через стек и возвращаются все результаты работы функций) кусок данных потенциально бесконечного размера, ну или просто достаточно крупного размера. Поэтому в C, функции не возвращают строки! На крайняк они возвращают УКАЗАТЕЛИ на строки. ( char и char* это как-бе разные вещи )
2. А как-же работают все строковые функции? Есть два метода, либо они сами выделяют память, шаманят в ней, а потом возвращают указатель char* на выделенный блок ( но это как-бе нестандартный для C подход ). Второй метод подразумевает что вы САМИ выделили кусок динамической памяти для строки, запомнили адрес этого куска в типизированном указателе char* ( то есть типа строку создали ) и передаёте этот указатель в строковую функцию, которая через указатель лезет в выделенный вами блок памяти и делает с ним разные интимные вещи.

То есть, если говорить о способах реализации и использования строковых функций в C, то :
А. Есть общепринятый велосипед с передачей в функцию указателя на уже инициализированную строку
Б. Есть другие велосипеды, реже используемые, с квадратными колёсами, но работоспособные


P.S. И да, в C++ можно возвращать из функции строки, не парясь с выделением памяти и указателями. Эти возможности реализуются либо стандартной библиотекой языка C++, либо сторонними библиотеками, из которых я могу назвать Qt, boost
P.P.S. И да, C и C++ это разные языки
Re[2]: нужен аналог функции format в Delphi/Builder
От: MASReady  
Дата: 19.09.11 13:57
Оценка:
Здравствуйте, 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);

...

//функция примерно как нарисовал уважаемый SaZ
char * 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
От: SaZ  
Дата: 19.09.11 15:01
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>это все понятно,


MAS>я про то что:

MAS>
MAS> char *str;
MAS>...
MAS> savetolog(my_fmtstr(str,fmt,"разные переменные указанные в строке формата %s,%d,...."));
MAS> free(str);
MAS>...
MAS>


Это всё страшное извращение, чреватое кучей ошибок). Зачем это нужно? Как тут уже выше давали ссылку, вот нормальный подход
Автор: remark
Дата: 11.12.10
. Или проблема в том, чтобы разобраться?
Re[3]: нужен аналог функции format в Delphi/Builder
От: dmitryalexeeff  
Дата: 20.09.11 00:46
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>
MAS>//создаем переменную - указатель:
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
От: MASReady  
Дата: 27.10.11 06:09
Оценка:
Вот что получилось в итоге, мож кому пригодится, главное не забыть когда строка станет ненужной сделать ей 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
От: MASReady  
Дата: 27.10.11 06:26
Оценка:
забыл про va_end
вот так:


char * format(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    char * result=NULL;
    int res=vsnprintf(result, 0, fmt, args);
    va_end(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);
        va_end(args);
    }
    return result;
};
Re: нужен аналог функции format в Delphi/Builder
От: баг  
Дата: 27.10.11 09:27
Оценка:
Здравствуйте, MASReady, Вы писали:

MAS>Нужна функция типа format в Delphi/Builder, чтобы возвращала строку


Так как в тегах С++, то может возвращать std::string? И никаких проблем с управлением памятью или возвратом указателей на локальные переменные
Re: нужен аналог функции format в Delphi/Builder
От: Vamp Россия  
Дата: 27.10.11 13:23
Оценка:
MAS>Пишу под Linux на KDevelop
KDevelop — это значит C++. Это значит, что пользуемся стандартными стримами и не паримся.
Да здравствует мыло душистое и веревка пушистая.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.