0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

std::string に printf のような書式付き出力をしたい

Last updated at Posted at 2025-03-27

1. はじめに

どこから拾ってきたのか忘れてしまいましたが、それを元に std::string に対して printf みたいな書式付き出力をするクラス(?) を作りました。format は C++20 から使えるようですが、こちらは C++11 くらいから使用でき、既存の使い方に慣れている方ならすぐ使えます。wchar_t版も用意しました。

2. ということで(Windows限定)コード

StringUtil.h

// StringUtil.h
#pragma once

#include    <stdexcept>
#include	<stdarg.h>
#include	<vector>
#include	<string>

class CStringUtil
{
public:
    static std::string format(const char *format, ...)
    {
        va_list marker;

        va_start(marker, format);
        size_t nSize = getFormatSize(format, marker);
        va_end(marker);

        if (nSize <= 0)
        {
            throw std::runtime_error("Failed to calculate format size.");
        }

        //  終端文字分を確保
        std::vector<char> vStr(nSize + 1, '\0'); 

        va_start(marker, format);
        int result = vsnprintf(vStr.data(), vStr.size(), format, marker);
        va_end(marker);

        if (result < 0)
        {
            throw std::runtime_error("String formatting failed.");
        }

        return std::string(vStr.data());
    }

    static std::wstring format(const wchar_t *format, ...)
    {
        va_list marker;
        
        va_start(marker, format);
        size_t nSize = getFormatSize(format, marker);
        va_end(marker);

        if (nSize <= 0)
        {
            throw std::runtime_error("Failed to calculate format size.");
        }

        //  終端文字分を確保
        std::vector<wchar_t> vStr(nSize + 1, L'\0');

        va_start(marker, format);
        int result = vswprintf(vStr.data(), vStr.size(), format, marker);
        va_end(marker);

        if (result < 0)
        {
            throw std::runtime_error("String formatting failed.");
        }

        return std::wstring(vStr.data());
    }

private:
    static int getFormatSize(const char *format, va_list args)
    {
        int size = vsnprintf(nullptr, 0, format, args);
        return size;
    }

    static int getFormatSize(const wchar_t *format, va_list args)
    {
        // note: this is for Windows only
        int size = _vscwprintf(format, args);
        return size;
    }

    CStringUtil() {}
    ~CStringUtil() {}
};

3. Windows以外はどうする?

wchar_t を与えた場合に 文字数を数える関数が見当たりません。
ということで /dev/null が使える環境限定になりますけれども、こんなコードはいかがでしょうか(一部抜粋)。


    static int getFormatSize(const wchar_t *format, va_list args)
    {
    	FILE* fp = fopen("/dev/null", "wb");
    	if(fp == nullptr) {
    		return -1;
    	}
    	int result = vfwprintf(fp, format, args);
    	fclose(fp);
        return result;
    }
0
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?