#c #c #string
#c #c #строка
Вопрос:
Я ищу sprintf на c .
Я хочу создать строку запроса mysql, но если я сделаю это следующим образом (max_limit — это const int
)
std::string query = "select * from bla limit " max_limit;
Запрос не будет работать.
Комментарии:
1. не отвечаю прямо на ваш вопрос, но подумайте об использовании
prepared statements
. Затем вы можете передатьmax_limit
в качестве аргумента, и это, как правило, лучше во многих отношениях.2. Если вы хотите написать исходный файл на нескольких языках (оба
C
иC
), я предлагаю вам не использовать::
илиnamespace
или<<
(за исключением случаев, когда это означает побитовый сдвиг) илиstring
…3. Я обнаружил, что формат Boost (предложенный @mkaes ниже) является лучшей альтернативой. Он очень гибкий и имеет довольно приличный синтаксис.
Ответ №1:
В C 11 это было сделано слишком просто. Использовать std::to_string()
как:
std::string query = "select * from bla limit " std::to_string(max_limit);
Готово!
СТАРОЕ РЕШЕНИЕ, для тех, кто все еще использует C 03.
Использовать stringbuilder
и создавать std::string
«на лету» как:
std::string query = stringbuilder() << "select * from bla limit " << max_limit;
где stringbuilder
реализован как:
struct stringbuilder
{
std::stringstream ss;
template<typename T>
stringbuilder amp; operator << (const T amp;data)
{
ss << data;
return *this;
}
operator std::string() { return ss.str(); }
};
Вы можете использовать stringbuilder
многими различными способами, такими как:
std::string g(int m, int n)
{
//create string on the fly and returns it
if ( m < n )
return stringbuilder() << m << " is less than " << n ;
return stringbuilder() << n << " is less than " << m ;
}
void f(const std::string amp; s );
//call f while creating string on the fly and passing it to the function
f(stringbuilder() << '{' << pc << '}' ); //passed as std::string
//this is my most favorite line
std::string s = stringbuilder() << 23 << " is greater than " << 5 ;
Смотрите демонстрацию в ideone :http://ideone.com/J995r
И посмотрите мой блог об этом: Создайте строку на лету всего в одной строке
Комментарии:
1. 1:
stringbuilder
Действительно хорош в средах, отличных от C 11.
Ответ №2:
Вам не нужен sprintf, он не работает со строками. Что-то вроде этого:
#include <sstream>
#include <string>
template <typename T>
std::string Str( const T amp; t ) {
std::ostringstream os;
os << t;
return os.str();
}
справится с задачей. Тогда вы можете сказать:
std::string query = "select * from bla limit " Str( max_limit );
Комментарии:
1. конечно, его проще сконструировать как,
std::ostringstream str("select * from bla limit "); str << max_limit;
тогда запрос простоstr.str()
…2. Нет, это не проще, это намного больше ввода, предполагая, что он хочет создавать подобные строки повсюду.
3. это не так однозначно, зависит от того, как запросы используют параметры, я бы не стал просто отклонять как «больше ввода»… в любом случае, это не имеет значения, суть в том, чтобы выделить
std::ostringstream
.
Ответ №3:
Может быть, вы хотите взглянуть на библиотеку boost::format. Он обеспечивает синтаксис sprintf с удобством c .
Итак, ваш пример был бы:
std::string str = (boost::format("select * from bla limit %d") % max_limit).str();
Комментарии:
1. Или, если вы рассматриваете boost,
lexical_cast<>
…?2. 1, зачем изобретать велосипед здесь, но давайте все равно сохраним его в надлежащем типобезопасном виде.
Ответ №4:
Или просто использовать макрос? #define QueryString(msg) ((static_cast<std::ostringstreamamp;>(std::ostringstream().seekp(0, std::ios_base::cur)<<msg)).str())
Использование: std::string query = QueryString("select * from mytable where x="<<30);
Комментарии:
1. На мой взгляд, это кажется хуже, чем предлагаемые шаблонные решения.
2. @awoodland: не могли бы вы объяснить, почему?
3. Шаблоны были в основном разработаны для преодоления недостатков макросов. Использование макросов вместо шаблонов здесь, похоже, не добавляет никакой ценности, но это поощряет запихивание всего в одну строку, запутывание и приводит к появлению в будущем целого класса случайных незаметных ошибок, которые были бы невозможны с шаблонами.
4. Вы заметили, что я НА САМОМ деле использую там класс STL? Макрос основан на шаблоне. Все, что он делает, это упрощает работу программиста. То есть вместо записи
std::ostringstream stream;stream<<"Answer to life is "<<42;string s = stream.str()
он делает это с помощьюstring s = QueryString("Answer to life is "<<42);
. Я действительно не понимаю вашей точки зрения.5. Я не голосовал против этого, потому что это не ужасно, я не голосовал за это, потому что это не лучшая практика. На мой взгляд, проблемы заключаются в том, что 1) Вы намеренно пытались сделать его не похожим на макрос в большинстве соглашений об именовании. 2) Любые синтаксические ошибки при использовании будут сбивать с толку любого пользователя, который не читал определение макроса. 3) Использование макроса вынудило вас использовать неестественный макет, что затрудняет чтение макроса 4) Существует очень реальный риск того, что кто-то через год, поддерживающий это, внесет ошибку двойной оценки, добавив новую функцию или исправив какую-либо другую проблему.