Как хранить объединение целых и символов в символе *? - PullRequest
1 голос
/ 02 октября 2010

У меня есть несколько целых чисел, скажем one two и three. Я хочу создать строку типа

char* example = "There are " + one + " bottles of water on " + 
    two + " shelves in room number " + three + "\n".`  

Это не работает в C / C ++. Как я могу сохранить этот тип значения в символе *?

Ответы [ 6 ]

7 голосов
/ 02 октября 2010

В C есть несколько способов сделать это, в зависимости от того, как вы хотите выделить память [*]. Для простого варианта выделения его из кучи:

len = snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
char *result = malloc(len+1);
if (result == 0) { /* handle error */ }
snprintf(result, len+1, "%d bottles, %d shelves, room %d\n", one, two, three);

/* some time later */
free(result);

Остерегайтесь нестандартных реализаций snprintf, которые не возвращают длину при превышении буфера. Проверьте свою документацию.

В C ++ snprintf не входит в стандарт, и даже там, где он доступен, приведенный выше код должен приводить к результату malloc [**]. C ++ добавляет возможность использования строковых потоков:

std::stringsteam r;
r << one << " bottles, " << two << " shelves, room " << three << "\n";
std::string result = r.str();

// if you absolutely need a char*, use result.c_str(), but don't forget that
// the pointer becomes invalid when the string, "result" ceases to exist.

Это экономит беспорядок при длине буфера, упрощает управление ресурсами и позволяет избежать риска с printf и друзьями, что вы можете передать аргумент неправильного типа для спецификатора формата. Обычно это предпочтительный вариант.

Однако в некоторых случаях он менее гибок: формат встроен в код, а не содержится в строке формата, поэтому сделать текст настраиваемым сложнее. Это также может быть немного сложнее для чтения, например, это не редкость, когда в первой версии любой такой строки кода пропускается символ пробела. Но если вы хотите использовать подход snprintf в C ++, а в вашей реализации доступен snprintf, то вы можете воспользоваться преимуществами более простого управления памятью в C ++ следующим образом:

len = std::snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
std::vector<char> r(len+1);
std::snprintf(&r[0], r.size(), "%d bottles, %d shelves, room %d\n", one, two, three);

char *result = &r[0];
// again, "result" is only valid as long as "r" is in scope

[*] Обратите внимание, что вы не можете «сохранить» строку в char*, потому что char* - это просто указатель. Вы можете хранить указатель на строку в char*, но сама строка - это совершенно отдельная вещь.

[**], потому что C и C ++ РАЗНЫЕ ЯЗЫКИ!

6 голосов
/ 02 октября 2010

C ++ не VB.Но у вас есть много вариантов.

stringstream:

#include <sstream>
#include <string>

stringstream ss;
ss<< "There are " << one << " bottles of water on " << two << " shelves in room number " << three;
string s = ss.str();

boost / format:

#include <boost/format.hpp>
#include <string>

string s = (boost::format("There are %1% bottles on %2% shelves in room number %3%")%one%two%three).str();

old-school (хакерский, небезопасный, плохой, не делайте этого)

char buffer[1024] = {};
sprintf(buffer, "There are %d bottles on %d shelves in room number %d", one, two, three); 
1 голос
/ 02 октября 2010
#include <sstream>

std::stringstream strVal;

strVal << std::string("There are ") << one << std::string(" bottles of water on ") << 
    two << std::string(" shelves in room number ") << three << std::endl;

std::string copyStr(strVal.str());
const char * example = copyStr.c_str();
1 голос
/ 02 октября 2010

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

0 голосов
/ 02 октября 2010

Мое решение:

template <typename T> std::string toStr(const T& something) {
    std::stringstream ss;
    ss << something;
    return ss.str();
}
...
std::string example = "There are " + toStr(one) + " bottles of water on " + 
                toStr(two) + " shelves in room number " + toStr(three) + "\n";
0 голосов
/ 02 октября 2010

Мне нравится строковый подход, но я использую класс, чтобы упростить его использование.Смотрите мой ответ на другой вопрос SO для более подробной информации:

string myString = MakeString() << "There are " << one << " 
      bottles of water on " << two << " shelves in room number " << three;

char * example = myString.c_str(); // if you really need a char *
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...