std::cout で出力する書式を指定する - C++ プログラミング

PROGRAM


std::cout で出力する書式を指定する

C++ で標準出力にテキストを出力したいときには <iostream> に定義されている std::cout を使うのが一般的です。

このとき C 言語の printf のときのように、出力する数値などの書式を指定したい場合には、その値を出力する前に std::cout の書式フラグ (fmtflag) や埋める文字 (fill) などを調整することでそれが可能になります。

ここでは std::cout について記載しますが、std::ostringstream などの std::ostream 系列についても同様です。

16 進数で出力する

数値を 16 進数で出力したい場合は、std::cout の setf 関数を使うことで行えます。

// 以降の数値出力を 16 進数で行います。

std::cout.setf(std::ios::hex, std::ios::basefield);

このようにすることで、ストリーム出力演算子を使って出力する数字が 16 進数で表示されるようになります。

このとき、これ以降の数値が全て 16 進数表記になることに注意します。これ以降、別の場所で std::cout を使ったときにも影響するので、後で記す方法で、使い終わったらフラグを元に戻しておくのが安全でしょう。

 

ところで setf 関数の第一引数では、出力する基数を指定しています。

std::ios::hex 数値を 16 進数で出力します。
std::ios::oct 数値を 8 進数で出力します。
std::ios::dec 数値を 10 進数で出力します。

これらのフラグはどれか 1 つしか適用されないため、第 2 引数では目的のもの以外がリセットされるように "std::ios::basefield" を指定しています。

 

出力する文字幅と表示位置、余ったところに埋める文字を指定する

出力する文字幅を指定する

たとえば数値を 10 文字分の表示スペースに表示したい場合には、値を出力する直前に <iomanip> に定義されている std::setw マニピュレータをストリームに出力します。

// 値 value を 10 文字分の表示スペースに出力します。

std::cout << std::setw(10) << value;

これで、10 文字分のスペースに value の値が出力されるようになります。

既定では、指定範囲内で右寄せで、余った部分は空白文字で埋められる様子でしたが、表示幅を指定する場合は意図したとおりに表示されるように、表示位置と埋める文字はその都度指定するのが安全です。

ちなみに、表示する内容が指定範囲に収まらなかった場合は、普通に全部が表示されます。

 

表示位置を指定する

文字幅に対して、その中のどこへ出力するかはフラグを使って指定できます。

たとえば、右寄せで表示したい場合は次のようにします。

// 以降の数値出力を、表示幅に対して右寄せで出力します。

std::cout.setf(std::ios::right, std::ios::adjustfield);

このようにすることで、ストリーム出力演算子を使って出力する値が、表示幅に対して右寄せで表示されるようになります。

このときも、これ以降の文字幅指定された出力が全て右寄せになることに注意します。これ以降、別の場所で std::cout を使ったときにも影響するので、後で記す方法で、使い終わったらフラグを元に戻しておくのが安全でしょう。

 

ところで setf 関数の第一引数では、どの位置に出力するかを指定しています。

std::ios::left 表示幅に対して左寄せで出力します。
std::ios::right 表示幅に対して右寄せで出力します。
std::ios::internal 表示幅に対して、値の符号を左側に、値を右側に出力します。

これらのフラグはどれか 1 つしか適用されないため、第 2 引数では目的のもの以外がリセットされるように "std::adjustfield" を指定しています。

 

表示幅の余分を埋める文字を指定する

表示幅を指定して出力した時、余った部分は既定では空白文字が出力されますが、fill 関数を使うことで任意の文字に変更できます。

// 表示幅の余った部分を '0' で埋めるようにします。

std::cout.fill('0');

このようにすることで、表示幅を指定してストリーム出力した時に、余った部分を '0' で埋めてくれるようになります。

右と左のどちらがこの文字で埋められるかは、前述した表示位置の指定によって変わってきます。

 

なお、このときも、これ以降の文字幅指定された出力の余分がこれで埋められるようになることに注意します。

これ以降、別の場所で std::cout を使ったときにも影響するので、後で記す方法で、使い終わったら元に戻しておくのが安全でしょう。

 

書式フラグの保存と復元

std::cout の書式フラグは、設定すると他の箇所での以降の出力にも影響するため、変更したら元に戻しておくのが理想的です。

現在設定されているフラグは flags 関数を使って取得できるので、変更前にこの値を保存しておきます。

// 現在のフラグを flagsSaved に保存しておきます。

std::ios::fmtflags flagsSaved = std::cout.flags();

その後で、フラグを変更して出力を行い、最後に次のようにしてフラグを元に戻します。

// フラグを、保存しておいた flagsSaved に戻します。

std::cout.flags(flagsSaved);

これで、他に影響を与えないで済むので、フラグを変更しての出力がしやすくなります。

flags 関数に設定するフラグを渡したときにも、変更前のフラグが戻り値で返されるので、設定と同時に従前のフラグを保存することも簡単です。

 

余分を埋める文字の保存と復元

std::cout で std::setw(n) マニピュレータを使って表示幅を指定したときに使う、余分を埋める文字も、設定すると他の箇所での以降の出力にも影響するため、変更したら元に戻しておくのが理想的です。

現在設定されている文字は、埋める文字を fill 関数で変更するのと同時に保存するのが簡単です。

// 現在の余分を埋める文字を '0' にしつつ、変更前のものを fillSaved に保存しておきます。

char fillSaved = std::cout.fill('0');

そして出力し終わったら、最後に次のようにして元に戻します。

// 埋める文字を、保存しておいた fillSaved に戻します。

std::cout.fill(fillSaved);

これで、これ以降の他の出力に影響を与えないで済みます。

ここで使っている fill 関数は、引数を指定しないと現在設定されている文字を返すので、変更しながらでなくても現在の値を保存できます。

 

書式フラグとマニピュレータ

書式フラグ

書式を設定する関数(一括指定の flags 関数、追加指定の setf 関数、除外指定の unsetf 関数)で使用できる書式フラグとしては、次のものがあるようです。

std::ios::hex 数値を 16 進数で出力します。setf 関数で設定するときは第二引数で std::ios::basefield マスクを指定することで、他の基数指定フラグを除外できます。
std::ios::oct 数値を 8 進数で出力します。setf 関数で設定するときは第二引数で std::ios::basefield マスクを指定することで、他の基数指定フラグを除外できます。
std::ios::dec 数値を 10 進数で出力します。setf 関数で設定するときは第二引数で std::ios::basefield マスクを指定することで、他の基数指定フラグを除外できます。
std::ios::showbase 数値を出力するときに、基数を示すテキストを表示します。16 進数なら "0x" が、8 進数なら "0" が、出力の先頭に付けられます。10 進数の場合は何も付きません。
std::ios::left 表示幅に対して左寄せで出力します。setf 関数で設定するときは第二引数で std::ios::adjustfield マスクを指定することで、他の位置指定フラグを除外できます。
std::ios::right 表示幅に対して右寄せで出力します。setf 関数で設定するときは第二引数で std::ios::adjustfield マスクを指定することで、他の位置指定フラグを除外できます。
std::ios::internal 表示幅に対して、値の符号を左側に、値を右側に出力します。setf 関数で設定するときは第二引数で std::ios::adjustfield マスクを指定することで、他の位置指定フラグを除外できます。
std::ios::skipws 先頭部分にある空白を読み飛ばします。
std::ios::noskipws 先頭部分にある空白を読み飛ばさないで扱います。
std::unitbuf 出力する度に出力バッファーをフラッシュします。
std::nounitbuf 出力する度ごとには出力バッファーをフラッシュしないようにします。
std::fixed 浮動小数点数を、10 進表記法で出力します。たとえば M_PI は "3.141593" と出力されます。
std::scientific 浮動小数点数を、科学的表記法で出力します。たとえば M_PI は "3.141593E+00" と出力されます。
std::showpoint 浮動小数点数を表示する際に、必ず小数点数を出力します。たとえば (float)10 なら "10.0000" と出力されます。(int)10 は "10" です。
std::showpos 数値を表示するときに、正の値でも "+" 符号を先頭に表示します。浮動小数点数についても同様です。
std::uppercase 16 進数表記や科学的表記法を、アルファベットを大文字にして出力します。std::boolalpha については適用されません。
std::boolalpha bool 値を "true" や "false" の文字列で出力します。このフラグが設定されていない場合は true は "1" に、false は "0" になります。

 

マニピュレータ

ストリーム演算子で使用できるマニピュレータには、次のものがあるようです。

std::setw(n) 表示幅を指定します。出力後にリセットされるので、その都度、指定する必要があります。
std::setfill('c') 表示幅を指定した時に、余分を埋める文字を指定します。マニピュレータの場合も以降の表示に影響するので、fill 関数で設定前の値を保存しておいて、最後に元に戻すようにするのが安全です。
std::left 表示幅に対して左寄せで出力します。マニピュレータの場合も以降の表示に影響するので、フラグを保存しておいて最後に元に戻すようにするのが安全です。
std::right 表示幅に対して右寄せで出力します。マニピュレータの場合も以降の表示に影響するので、フラグを保存しておいて最後に元に戻すようにするのが安全です。
std::internal 表示幅に対して、値の符号を左側に、値を右側に出力します。マニピュレータの場合も以降の表示に影響するので、フラグを保存しておいて最後に元に戻すようにするのが安全です。
std::endl 改行文字を出力して、出力バッファをフラッシュします。
std::ends 文字列の末端を示す '\0' をバッファに出力します。
std::flush 出力バッファをフラッシュします。
std::ws 空白文字を読み飛ばして入力するようにします。

[ もどる ]