사용자 제공 char*
에 쓰는 대신 std :: string을 반환하여 자동 할당 sprintf를 수행하는 함수를 작성했습니다. (IOSTREAMS 또는 Boost.Format이나 친구를 추천 어떤 답변을 바랍니다 -. 나는 다른 상황에서 그들을 사용합니까, 그들이 존재 알고,하지만 요구 사항이 특정 사건에 대한이)std :: string 및 stdarg.h
std::string FormatString(const std::string& format, va_list argList)
{
char smallBuffer[500], *text = smallBuffer;
int length = _countof(smallBuffer);
// MSVC is not C99 conformant, so its vsnprintf returns -1
// on insufficient buffer space
int outputSize = _vsnprintf(text, length, format.c_str(), argList);
while (outputSize < 0 && errno == ERANGE && length > 0)
{
length <<= 1;
if (text != smallBuffer) { delete[] text; }
text = new char[length];
outputSize = _vsnprintf(text, length, format.c_str(), argList);
}
if (outputSize < 0)
{
throw std::runtime_error("Failed to format string.");
}
std::string ret(text);
if (text != smallBuffer)
{
delete[] text;
}
return ret;
}
std::string FormatString(const std::string& format, ...)
{
va_list argList;
va_start(argList, format);
std::string result;
try
{
result = FormatString(format, argList);
}
catch(...)
{
va_end(argList);
throw;
}
va_end(argList);
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int foo = 1234;
std::string bar = "BlaBla";
std::cout << FormatString("%i (%s)", foo, bar.c_str()) << std::endl;
return 0;
}
을 (그리고 네, C++ 형식의 문자열을 C++ 형식의 문자열로 파이프하는 것의 아이러니가 있습니다. 이것은 단지 테스트 코드 일뿐입니다.)
불행히도 VS2008을 사용하면 잘못된 인수를 읽었 기 때문에 printf 내부의 내부에서 심하게 부숴졌습니다. va_list
(디버거에 따르면 va_start
다음에 "실제"첫 번째 매개 변수 바로 앞의 4 바이트 null 시퀀스를 가리킴).
특히 variadic 함수에서 const std::string& format
을 단지 std::string format
(즉, 값으로 전달)으로 변경하면 올바르게 작동합니다. 물론 그것은 const char *
으로 변경하면됩니다.
이것은 일종의 컴파일러 버그입니까, 아니면 참조 매개 변수와 함께 va_list를 사용하는 것이 합법적이지 않습니까?
[참조 매개 변수와 함께 varargs를 사용하는 문제가 있습니까?] (http://stackoverflow.com/questions/222195/are-there-gotchas-using-varargs-with-reference-parameters). –
감사합니다. 거기에도 좋은 설명이 있습니다. 부끄러움이 내 사전 쿼리 검색에서 나오지 않았다. :) – Miral