Могу ли я измерить необходимый буфер для sprintf в Microsoft C ++? - PullRequest
3 голосов
/ 15 февраля 2010

Я пишу небольшую консольную программу с проверкой концепции для Visual Studio 2008 и хочу, чтобы она выводила цветной текст для удобства чтения. Для простоты кодирования я также хотел сделать быструю замену printf, что-то, что я мог бы написать так:

MyPrintf(L"Some text \1[bright red]goes here\1[default]. %d", 21);

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

Однако я ударил стену по wsprintf, потому что не могу найти функцию, которая позволила бы мне определить требуемый размер буфера, прежде чем передать его в функцию. Я мог бы, конечно, выделить 1 МБ, чтобы быть уверенным, но это было бы не красиво, и я бы предпочел оставить это как решение для резервного копирования, если я не могу найти лучший способ.

Кроме того, в качестве альтернативы я рассматриваю возможность использования std::wstring (на самом деле, я больше похож на парня из C с небольшим опытом работы с C ++, поэтому мне пока проще найти простые старые char-массивы), но в этом нет ничего как wsprintf, где вы можете построить строку с замененными значениями в них.

Итак ... что мне делать?

Ответы [ 6 ]

4 голосов
/ 15 февраля 2010

Ваш вопрос помечен C ++, и в этом случае я бы сказал, что std :: wstringstream - это путь. Пример:

#include <sstream>

void func()
{
    // ...

    std::wstringstream ss;  // the string stream

    // like cout, you can add strings and numbers by operator<<
    ss << L"Some text \1[bright red]goes here\1[default]. " << 21;

    // function takes a C-style const wchar_t* string
    some_c_function(ss.str().c_str()); // convert to std::wstring then const wchar_t*
    // note: lifetime of the returned pointer probably temporary
    // you may need a permanent std::wstring to return the c_str() from
    // if you need it for longer.

    // ...
}
3 голосов
/ 15 февраля 2010

Вы хотите _snwprintf . Эта функция принимает размер буфера, и если буфер недостаточно велик, просто удвойте размер буфера и попробуйте снова. Чтобы избежать необходимости выполнять несколько вызовов _snwprintf каждый раз, следите за размером буфера, который вы использовали в прошлый раз, и всегда начинайте с него. Вы будете делать несколько лишних звонков здесь и там, и вы будете время от времени тратить немного оперативной памяти, но это прекрасно работает и не может ничего переиграть.

3 голосов
/ 15 февраля 2010

Я бы пошел на строковый поток C ++. Он не такой компактный, как sprintf, но даст вам необходимую функциональность.

2 голосов
/ 15 февраля 2010

Если вы можете позволить себе использовать повышение, вы можете рассмотреть boost::format. Это даст вам гибкость std::string с и функции форматирования sprintf. Он довольно сильно отличается от C-стиля, но также довольно прост в использовании. Вот пример .

1 голос
/ 30 августа 2013

_scprintf, _scprintf_l, _scwprintf, _scwprintf_l

Эта функция возвращает количество символов в отформатированной строке.

0 голосов
/ 15 февраля 2010

Использование std::wstring кажется хорошим решением, если вы планируете передавать строки между вашими объектами - оно обрабатывает размер и имеет хороший метод c_str, который даст вам массив широких символов.

Дополнительным преимуществом является то, что вы можете передавать его по ссылке, а не по указателю.

Когда вам нужна строка actall, просто используйте метод c_str:

wprintf(L"string %s recieved!", myWString.c_str());
...