웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

std::string assign format string

std::string 에는 format을 지정하여 입력하는 기능이 따로 없습니다. 그렇기 때문에 MFC에서 CString.Format처럼 간편하게 쓸만한걸 직접 만들어 사용하거나 boost::format을 사용하는 방법이 있습니다. 그중 만들어 사용하는 몇 가지를 소개하겠습니다.

 

예전부터 내려오는 방법으로 parameter에 ... 을 두어 가변 인자를 전달받는 방법입니다.

가변 인자를 전달받기 위해서는 가장 중요한 Calling Convention__cdecl 이어야 한다는 점입니다.

 

 

Calling Convention이 궁금하신 분들은 아래 링크를 참조해주세요

https://wendys.tistory.com/22

 

__cdecl, __stdcall, __fastcall x86 호출 규약(Calling Convention)

Calling Convention X86에선 호출 규약이 __cdecl, __stacll, __fastcall 등으로 나누어있지만 x64에선 __fastcall 하나의 호출 규약만을 사용하도록 정의 되어있습니다. 오늘은 x86 호출 규약에 대해서만 정리를..

wendys.tistory.com

 

 

format string sample 1

가변 인자를 va_list로 순회하여 사용한 방법이고, sample2 방법은 snprintf를 사용한 방법입니다. n이 붙지 않은 sprintf는 스택 오버플로우 등 수많은 취약점에 이용된 API이기 때문에 절대 사용 금지입니다!

 

#include <stdarg.h>

std::string format_string(const std::string fmt, ...) {
    int size = ((int)fmt.size()) * 2;
    std::string buffer;
    va_list ap;
    while (1) {
        buffer.resize(size);
        va_start(ap, fmt);
        int n = vsnprintf((char*)buffer.data(), size, fmt.c_str(), ap);
        va_end(ap);
        if (n > -1 && n < size) {
            buffer.resize(n);
            return buffer;
        }
        if (n > -1)
            size = n + 1;
        else
            size *= 2;
    }
    return buffer;
}

int main()
{
    std::string test_message = format_string("%d %lf %s %#x\n", 10, 10.5, "test message", 12345678);
    printf(test_message.c_str());

    system("pause");
}

 

 

format string sample 2

#include <memory>
#include <string>

template<typename ... Args>
std::string format_string(const std::string& format, Args ... args)
{
    size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;
    std::unique_ptr<char[]> buffer(new char[size]);
    snprintf(buffer.get(), size, format.c_str(), args ...);
    return std::string(buffer.get(), buffer.get() + size - 1);
}

int main()
{
    std::string test_message = format_string("%d %lf %s %#x\n", 10, 10.5, "test message", 12345678);
    printf(test_message.c_str());

    system("pause");
}

 

 

TIP

만약 declared 처리된 sprintf를 사용하고 싶은 경우 빌드 할때마다 warning 표시가 나오게 됩니다. 그럴 땐 다음과 같이 #pragma warning(disable : 4996) 을 이용하여 warning message를 제거할 수 있습니다. 위 코드는 snprintf를 사용하기 때문에 warning 4996이 나타나지 않습니다.

 

#pragma warning(disable : 4996)

 

 

 

std::string을 std::wstring으로 변환하고 싶은 경우 다음 포스팅을 참조하세요

https://wendys.tistory.com/84

 

[C/C++] convert std::string <-> std::wstring <-> utf-8

convert ansi string to unicode string and utf-8 string c/c++에서 ansi string과 unicode string, utf-8 string을 상호 변환하기 위해서는 간단한 대입으로는 불가능합니다. 예전에 소개해드렸던 std::string.a..

wendys.tistory.com

 

반응형