🌕

printfについてまとめてみた

2022/01/03に公開

printf関数とは

「文字」、「数字」、「文字列」など、あらゆるものを出力する関数。


返り値

INT型で、出力した文字列のバイト数を返す。

エラーの場合はー1を返す。


フォーマット

%sのようにsなどの「変換指定子」さえあれば出力が可能だが、以下が詳細なフォーマット。

%[フラグ] [フィールド幅].[精度][長さ修飾子][変換指定子]

以下が対応する英語。
%[flags][width].[precision][length][specifier]

それでは一つずつ見ていこう。


%とは?

%は「これから変換の指定をしますよ」というサインで、printfでは必ず%が使用される。


フラグの種類

フラグ 説明
- 左揃えにする。(フィールド幅指定の揃え)
0 変換した値の左側を空白の代わりに0で埋める。
+ 符号付き変換。負の場合に-、正の場合には+の符号をつける。
(space) 符号付き変換で、負の場合にのみ-の符号がつくが、正の場合に符号の位置に半角スペースを配置する。
# 変換形式を変更。o変換(8進数)で先頭文字が必ず0になるように変換。xとX変換(16進数)で先頭に0x(Xの場合0X)がつくように変換。 実数変換では小数点に続く数字がないときでも小数点をつける。gとG変換では、末尾の0が削除されない。

フラグの例

-」フラグ

	指定例		           出力結果	 
printf("[%10d]\n", 1);	 	 [         1] 
printf("[%-10d]\n", 1);	 	 [1         ]
printf("[%10f]\n", 1.0);	 [  1.000000] 
printf("[%-10f]\n", 1.0);	 [1.000000  ]
printf("[%10s]\n", "1234");	 [      1234]
printf("[%-10s]\n", "1234");	 [1234      ]

上記の例では、左揃えであることを見やすくするために、のちほど紹介する「フィールド幅」を使用。
ここではフィールド値を10に設定しており、10文字分表示させている。

加えて左揃えを見やすくするため、カッコ[]を記入している。

3つ目の例で小数点第6位まで表示されている理由は、のちほど変換指定子の項目で説明する。


0」フラグ

	指定例		          出力結果	 
printf("[%10d]\n", 1);		[         1]
printf("[%010d]\n", 1);		[0000000001]
printf("[%10f]\n", 1.0);	[  1.000000]
printf("[%010f]\n", 1.0);	[001.000000]

ダメな例

printf("[%010s]\n", "1234");

→[0]フラッグは数値に対応し、sは文字列なのでコンパイルができない。以下エラーメッセージ。
'0' results in undefined behavior with 's' conversion specifier


+」フラグ

	指定例		       出力結果	 
printf("[%+d]\n", 1);		[+1]
printf("[%+d]\n", -1);		[-1]
printf("[%+f]\n", 1.0);		[+1.000000]
printf("[%+f]\n", -1.0);	[-1.000000]

(space)」フラグ

	指定例		       出力結果	 
printf("[% d]\n", 1);		[ 1]
printf("[% d]\n", -1);		[-1]
printf("[% f]\n", 1.0);		[ 1.000000]
printf("[% f]\n", -1.0);	[-1.000000]  

printf("[%10d]\n", 1);		[         1]
printf("[% 10d]\n", 1);		[         1]
printf("[%10d]\n", -1);		[        -1]
printf("[% 10d]\n", -1);	[        -1]

printf("[%10f]\n", 1.0);	[  1.000000]
printf("[% 10f]\n", 1.0);	[  1.000000]
printf("[%10f]\n", -1.0);	[ -1.000000]
printf("[% 10f]\n", -1.0);	[ -1.000000]  

#」フラグ

	指定例		       出力結果	 
	
printf("[%o]\n", 10);		[12]
printf("[%#o]\n", 10);		[012]

printf("[%x]\n", 10);		[a]
printf("[%#x]\n", 10);		[0xa]

printf("[%X]\n", 10);		[A]
printf("[%#X]\n", 10);		[0XA]

printf("[%#f]\n", 1.0);		[1.000000]
printf("[%.0f]\n", 1.0);	[1]	
printf("[%#.0f]\n", 1.0);	[1.]
printf("[%#.1f]\n", 1.0);	[1.0]

printf("[%g]\n", 1.0);		[1]
printf("[%#g]\n", 1.0);		[1.00000]
printf("[%#.0g]\n", 1.0);	[1.]

printf("[%G]\n", 1.0);		[1]
printf("[%#G]\n", 1.0);		[1.00000]
printf("[%#.0G]\n", 1.0);	[1.]

上記の例では、「実数変換では小数点に続く数字がないときでも小数点をつける」ことを示すために、のちほど紹介する「精度」を使用。

この例(f変換)では、小数点以下に表示する桁数を指定している。


- サンプルコード

サンプルコード
#include <stdio.h>

int main(void)
{
	//'-'flag
	printf("[%10d]\n", 1);
	printf("[%-10d]\n", 1);

	printf("[%10f]\n", 1.0);
	printf("[%-10f]\n", 1.0);

	printf("[%10s]\n", "1234");
	printf("[%-10s]\n", "1234");

	//'0'flag
	printf("[%10d]\n", 1);
	printf("[%010d]\n", 1);

	printf("[%10f]\n", 1.0);
	printf("[%010f]\n", 1.0);

	//'+'flag
	printf("[%+d]\n", 1);
	printf("[%+d]\n", -1);

	printf("[%+f]\n", 1.0);
	printf("[%+f]\n", -1.0);

	//'(space)'flag
	printf("[% d]\n", 1);
	printf("[% d]\n", -1);

	printf("[% f]\n", 1.0);
	printf("[% f]\n", -1.0);

	printf("[%10d]\n", 1);
	printf("[% 10d]\n", 1);
	printf("[%10d]\n", -1);
	printf("[% 10d]\n", -1);

	printf("[%10f]\n", 1.0);
	printf("[% 10f]\n", 1.0);
	printf("[%10f]\n", -1.0);
	printf("[% 10f]\n", -1.0);

	printf("[%-10f]\n", 1.0);
	printf("[%-10f]\n", -1.0);

	//'#"flag
	printf("[%o]\n", 10);
	printf("[%#o]\n", 10);

	printf("[%x]\n", 10);
	printf("[%#x]\n", 10);

	printf("[%X]\n", 10);
	printf("[%#X]\n", 10);

	printf("[%.0f]\n", 1.0);
	printf("[%#.0f]\n", 1.0);

	printf("[%g]\n", 1.0);
	printf("[%#g]\n", 1.0);
	printf("[%#.0g]\n", 1.0);

	printf("[%G]\n", 1.0);
	printf("[%#G]\n", 1.0);
	printf("[%#.0G]\n", 1.0);
}

フラッグを同時に使えるかどうか

※テーブル内の数字は、下記の出力結果やサンプルコード内の番号に対応。

↓こちらが先頭 「-」フラグ 0」フラグ 「+」フラグ 「(space)」フラグ 「#」フラグ
「-」フラグ -------- 1: ERROR 2: OK 3: OK 4: OK
0」フラグ 5: ERROR -------- 6: OK 7: OK 8: OK
「+」フラグ 9: OK 10: OK -------- 11: ERROR 12: ERROR
(space)」フラグ 13: OK 14: OK 15: ERROR -------- 16: ERROR
「#」フラグ 17: OK 18: OK 19: ERROR 20: ERROR --------
	指定例		       出力結果	
2: '-'flag + '+'flag
printf("[%-+d]\n", 1);		[+1]
printf("[%-+d]\n", -1);		[-1]
printf("[%-+10d]\n", 1);	[+1        ]
printf("[%-+10d]\n", -1);	[-1        ]

printf("[%-+f]\n", 1.0);	[+1.000000]	
printf("[%-+f]\n", -1.0);	[-1.000000]
printf("[%-+10f]\n", 1.0);	[+1.000000 ]	
printf("[%-+10f]\n", -1.0);	[-1.000000 ]	

3: '-'flag + '(space)'flag
printf("[%- d]\n", 1);		[ 1]
printf("[%- d]\n", -1);		[-1]
printf("[%- 10d]\n", 1);	[ 1        ]	
printf("[%- 10d]\n", -1);	[-1        ]	

printf("[%- f]\n", 1.0);	[ 1.000000]	
printf("[%- f]\n", -1.0);	[-1.000000]	
printf("[%- 10f]\n", 1.0);	[ 1.000000 ]	
printf("[%- 10f]\n", -1.0);	[-1.000000 ]	

4: '-'flag + '#'flag		
printf("[%-#o]\n", 10);		[012]	
printf("[%-#10o]\n", 10);	[012       ]	
		
6: '0'flag + '+'flag
printf("[%0+d]\n", 1);		[+1]
printf("[%0+d]\n", -1);		[-1]
printf("[%0+10d]\n", 1);	[+000000001]	
printf("[%0+10d]\n", -1);	[-000000001]	

printf("[%0+f]\n", 1.0);	[+1.000000]	
printf("[%0+f]\n", -1.0);	[-1.000000]	
printf("[%0+10f]\n", 1.0);	[+01.000000]	
printf("[%0+10f]\n", -1.0);	[-01.000000]	

7: '0'flag + '(space)'flag
printf("[%0 d]\n", 1);		[ 1]
printf("[%0 d]\n", -1);		[-1]
printf("[%0 10d]\n", 1);	[ 000000001]
printf("[%0 10d]\n", -1);	[-000000001]	

printf("[%0 f]\n", 1.0);	[ 1.000000]
printf("[%0 f]\n", -1.0);	[-1.000000]
printf("[%0 10f]\n", 1.0);	[ 01.000000]	
printf("[%0 10f]\n", -1.0);	[-01.000000]	

8: '0'flag + '#'flag
printf("[%0#o]\n", 10);		[012]
printf("[%0#10o]\n", 10);	[0000000012]	

9: '+'flag + '-'flag
printf("[%+-d]\n", 1);		[+1]	
printf("[%+-d]\n", -1);		[-1]
printf("[%+-10d]\n", 1);	[+1        ]	
printf("[%+-10d]\n", -1);	[-1        ]	

printf("[%+-f]\n", 1.0);	[+1.000000]	
printf("[%+-f]\n", -1.0);	[-1.000000]	
printf("[%+-10f]\n", 1.0);	[+1.000000 ]	
printf("[%+-10f]\n", -1.0);	[-1.000000 ]	

10: '+'flag + '0'flag
printf("[%+0d]\n", 1);		[+1]
printf("[%+0d]\n", -1);		[-1]
printf("[%+010d]\n", 1);	[+000000001]	
printf("[%+010d]\n", -1);	[-000000001]	

printf("[%+0f]\n", 1.0);	[+1.000000]	
printf("[%+0f]\n", -1.0);	[-1.000000]	
printf("[%+010f]\n", 1.0);	[+01.000000]
printf("[%+010f]\n", -1.0);	[-01.000000]	

13: '(space)'flag + '-'flag
printf("[% -d]\n", 1);		[ 1]
printf("[% -d]\n", -1);		[-1]
printf("[% -10d]\n", 1);	[ 1        ]	
printf("[% -10d]\n", -1);	[-1        ]

printf("[% -f]\n", 1.0);	[ 1.000000]	
printf("[% -f]\n", -1.0);	[-1.000000]	
printf("[% -10f]\n", 1.0);	[ 1.000000 ]	
printf("[% -10f]\n", -1.0);	[-1.000000 ]

14: '(space)'flag + '0'flag
printf("[% 0d]\n", 1);		[ 1]
printf("[% 0d]\n", -1);		[-1]
printf("[% 010d]\n", 1);	[ 000000001]	
printf("[% 010d]\n", -1);	[-000000001]	

printf("[% 0f]\n", 1.0);	[ 1.000000]	
printf("[% 0f]\n", -1.0);	[-1.000000]	
printf("[% 010f]\n", 1.0);	[ 01.000000]	
printf("[% 010f]\n", -1.0);	[-01.000000]	

17: '#'flag + '-'flag	
printf("[%#-o]\n", 10);		[012]
printf("[%#-10o]\n", 10);	[012       ]	

18: ' #'flag + '0'flag
printf("[%#0o]\n", 10);		[012]
printf("[%#010o]\n", 10);	[0000000012]	

- サンプルコード

サンプルコード
#include <stdio.h>

int main(void)
{
//1: '-'flag + '0'flag : ERROR
/*
	printf("[%-0d]\n", 1);
	printf("[%-0d]\n", -1);
	printf("[%-010d]\n", 1);
	printf("[%-010d]\n", -1);
*/

//2: '-'flag + '+'flag
	printf("[%-+d]\n", 1);
	printf("[%-+d]\n", -1);
	printf("[%-+10d]\n", 1);
	printf("[%-+10d]\n", -1);

	printf("[%-+f]\n", 1.0);
	printf("[%-+f]\n", -1.0);
	printf("[%-+10f]\n", 1.0);
	printf("[%-+10f]\n", -1.0);
//3: '-'flag + '(space)'flag
	printf("[%- d]\n", 1);
	printf("[%- d]\n", -1);
	printf("[%- 10d]\n", 1);
	printf("[%- 10d]\n", -1);

	printf("[%- f]\n", 1.0);
	printf("[%- f]\n", -1.0);
	printf("[%- 10f]\n", 1.0);
	printf("[%- 10f]\n", -1.0);

//4: '-'flag + '#'flag
	printf("[%-#o]\n", 10);
	printf("[%-#10o]\n", 10);

//5: '0'flag + '-'flag : ERROR
/*
	printf("[%0-d]\n", 1);
	printf("[%0-d]\n", -1);
	printf("[%0-10d]\n", 1);
	printf("[%0-10d]\n", -1);
*/

//6: '0'flag + '+'flag
	printf("[%0+d]\n", 1);
	printf("[%0+d]\n", -1);
	printf("[%0+10d]\n", 1);
	printf("[%0+10d]\n", -1);

	printf("[%0+f]\n", 1.0);
	printf("[%0+f]\n", -1.0);
	printf("[%0+10f]\n", 1.0);
	printf("[%0+10f]\n", -1.0);

//7: '0'flag + '(space)'flag
	printf("[%0 d]\n", 1);
	printf("[%0 d]\n", -1);
	printf("[%0 10d]\n", 1);
	printf("[%0 10d]\n", -1);

	printf("[%0 f]\n", 1.0);
	printf("[%0 f]\n", -1.0);
	printf("[%0 10f]\n", 1.0);
	printf("[%0 10f]\n", -1.0);

//8: '0'flag + '#'flag
	printf("[%0#o]\n", 10);
	printf("[%0#10o]\n", 10);

//9: '+'flag + '-'flag
	printf("[%+-d]\n", 1);
	printf("[%+-d]\n", -1);
	printf("[%+-10d]\n", 1);
	printf("[%+-10d]\n", -1);

	printf("[%+-f]\n", 1.0);
	printf("[%+-f]\n", -1.0);
	printf("[%+-10f]\n", 1.0);
	printf("[%+-10f]\n", -1.0);

//10: '+'flag + '0'flag
	printf("[%+0d]\n", 1);
	printf("[%+0d]\n", -1);
	printf("[%+010d]\n", 1);
	printf("[%+010d]\n", -1);

	printf("[%+0f]\n", 1.0);
	printf("[%+0f]\n", -1.0);
	printf("[%+010f]\n", 1.0);
	printf("[%+010f]\n", -1.0);

//11: '+'flag + '(space)'flag : ERROR
/*
	printf("[%+ d]\n", 1);
	printf("[%+ d]\n", -1);
	printf("[%+ 10d]\n", 1);
	printf("[%+ 10d]\n", -1);
*/

//12: '+'flag + '#'flag : ERROR
/*
	printf("[%+#o]\n", 10);
	printf("[%+#10o]\n", 10);
*/

//13: '(space)'flag + '-'flag
	printf("[% -d]\n", 1);
	printf("[% -d]\n", -1);
	printf("[% -10d]\n", 1);
	printf("[% -10d]\n", -1);

	printf("[% -f]\n", 1.0);
	printf("[% -f]\n", -1.0);
	printf("[% -10f]\n", 1.0);
	printf("[% -10f]\n", -1.0);


//14: '(space)'flag + '0'flag
	printf("[% 0d]\n", 1);
	printf("[% 0d]\n", -1);
	printf("[% 010d]\n", 1);
	printf("[% 010d]\n", -1);

	printf("[% 0f]\n", 1.0);
	printf("[% 0f]\n", -1.0);
	printf("[% 010f]\n", 1.0);
	printf("[% 010f]\n", -1.0);

//15: '(space)'flag + '+'flag : ERROR
/*
	printf("[% +d]\n", 1);
	printf("[% +d]\n", -1);
	printf("[% +10d]\n", 1);
	printf("[% +10d]\n", -1);
*/

//16: '(space)'flag + '#'flag : ERROR
/*
	printf("[% #o]\n", 10);
	printf("[% #10o]\n", 10);
*/

//17: '#'flag + '-'flag
	printf("[%#-o]\n", 10);
	printf("[%#-10o]\n", 10);

//18: ' #'flag + '0'flag
	printf("[%#0o]\n", 10);
	printf("[%#010o]\n", 10);

//19: '#'flag + '+'flag : ERROR
/*
	printf("[%#+o]\n", 10);
	printf("[%#+10o]\n", 10);
*/

//20: '#'flag + '(space)'flag : ERROR
/*
	printf("[%# o]\n", 10);
	printf("[%# 10o]\n", 10);
*/
	return (0);
}

フィールド幅

「最小幅」、「最小フィールド幅」とも呼ばれる。

何文字で出力するかを指定できる。

フィールド幅が、変換した結果より大きい場合、左側が空白で埋められる。

数字(0~9)

整数の場合 (変換指定子がdoなど)

出力内容が指定桁数を超える場合、変化なし。

	指定例		         出力結果	
printf("[%0d]\n", 1234567);	[1234567]
printf("[%5d]\n", 1234567);	[1234567]
printf("[%5d]\n", -1234567);	[1234567]
	

出力内容が指定桁数に満たない場合、左側をスペースで埋める。

	指定例		       	   出力結果	
printf("[%10d]\n", 1234567);	[   1234567]
printf("[%10d]\n", -1234567);	[  -1234567]


変換指定子がf, e, Eの場合

変化なし。

以下の例では、[123.321000]000が出現するが、これは後ほど紹介する「精度」にて解説。

自動的に小数点第6位までが表示される。

	指定例		        	  出力結果	
printf("[%0f]\n", 123.321);		[123.321000]
printf("[%5f]\n", 123.321);		[123.321000]
printf("[%10f]\n", 123.321);		[123.321000]
printf("[%10f]\n", -123.321);		[-123.321000]

printf("[%0f]\n", 1234567.7654321);	[1234567.765432]
printf("[%5f]\n", 1234567.7654321);	[1234567.765432]
printf("[%10f]\n", 1234567.7654321);	[1234567.765432]
printf("[%10f]\n", -1234567.7654321);	[-1234567.765432]


変換指定子がg, Gの場合

フィールド幅を指定しない場合。

	指定例		    	   出力結果	
printf("[%g]\n", 123.321);	 [123.321]
printf("[%g]\n", -123.321);	 [-123.321]

出力内容が指定桁数を超える場合、変化なし。

	指定例		    	   出力結果	
printf("[%0g]\n", 123.321);	 [123.321]
printf("[%5g]\n", 123.321);	 [123.321]

出力内容が指定桁数に満たない場合、左側をスペースで埋める。
整数部と小数部を合わせた桁数を指定。

	指定例		     	  出力結果	
printf("[%10g]\n", 123.321);	        [   123.321]
printf("[%10g]\n", -123.321);	        [  -123.321]
printf("[%20g]\n", 1234567.7654321);  	[         1.23457e+06]
printf("[%20g]\n", -1234567.7654321);	[        -1.23457e+06]

1.23457e+06と指数表示が出力されているが、e+06とは何かをのちほど変換指定子の項目で説明。


文字列の場合

整数と同様、出力内容が指定桁数を超える場合、変化はなく、
出力内容が指定桁数に満たない場合、左側をスペースで埋める。

	指定例		       出力結果	
printf("[%s]\n", "apple");	[apple]
printf("[%3s]\n", "apple");	[apple]
printf("[%10s]\n", "apple");	[     apple]

0をフィールド幅として指定すると、コンパイルできない。

printf("[%0s]\n", "apple");    // コンパイルエラー

*(アスタリスク)

*(アスタリスク)は、引数を使って数値を指定することができる。

下の例では10をフィールド幅に指定している。

	指定例		       出力結果	
printf("[%*d]\n", 10, 1234567);	[   1234567]

引数には変数を使うことも可能で、以下は変数を使って上記を書き直したもの。

int a = 10;
printf("[%*d]\n", a, 1234567);	[   1234567]

- サンプルコード

サンプルコード
#include <stdio.h>

int main(void)
{
// 整数の場合 (変換指定子が`d`や`o`など) 
	printf("[%d]\n", 1234567);
	printf("[%d]\n", -1234567);

	printf("[%0d]\n", 1234567);
	printf("[%5d]\n", 1234567);

	printf("[%10d]\n", 1234567);
	printf("[%10d]\n", -1234567);
	

// 変換指定子が`f`, `e`, `E`の場合
	printf("[%f]\n", 123.321);
	printf("[%f]\n", -123.321);

	printf("[%0f]\n", 123.321);
	printf("[%5f]\n", 123.321);

	printf("[%10f]\n", 123.321);
	printf("[%10f]\n", -123.321);

	printf("[%f]\n", 1234567.7654321);
	printf("[%f]\n", -1234567.7654321);

	printf("[%0f]\n", 1234567.7654321);
	printf("[%5f]\n", 1234567.7654321);

	printf("[%10f]\n", 1234567.7654321);
	printf("[%10f]\n", -1234567.7654321);


//変換指定子が`g`, `G`の場合
	printf("[%g]\n", 123.321);
	printf("[%g]\n", -123.321);

	printf("[%0g]\n", 123.321);
	printf("[%5g]\n", 123.321);

	printf("[%10g]\n", 123.321);
	printf("[%10g]\n", -123.321);

	printf("[%20g]\n", 1234567.7654321);
	printf("[%20g]\n", -1234567.7654321);

//文字列の場合
	printf("[%s]\n", "apple");
	printf("[%3s]\n", "apple");
	printf("[%10s]\n", "apple");
//以下'*'の場合
// 整数の場合 (変換指定子が`d`や`o`など) 
	printf("[%*d]\n", 0, 1234567);
	printf("[%*d]\n", 5, 1234567);

	int	a = 10;
	printf("[%*d]\n", a, 1234567);
	printf("[%*d]\n", 10, 1234567);
	printf("[%*d]\n", 10, -1234567);
// 変換指定子が`f`, `e`, `E`の場合

	printf("[%*f]\n", 0, 123.321);
	printf("[%*f]\n", 5, 123.321);

	printf("[%*f]\n", 10, 123.321);
	printf("[%*f]\n", 10, -123.321);

	printf("[%*f]\n", 10, 1234567.7654321);
	printf("[%*f]\n", 10, -1234567.7654321);

//変換指定子が`g`, `G`の場合
	printf("[%*g]\n", 0, 123.321);
	printf("[%*g]\n", 5, 123.321);

	printf("[%*g]\n", 10, 123.321);
	printf("[%*g]\n", 10, -123.321);

	printf("[%*g]\n", 20, 1234567.7654321);
	printf("[%*g]\n", 20, -1234567.7654321);

//文字列の場合
	printf("[%*s]\n", 3, "apple");
	printf("[%*s]\n", 10, "apple");
		return (0);
}


精度

「精度」は変換指定子によって意味が異なる。
直前にある.(ピリオド)と合わせて記述する必要が有る。

整数変換の場合

フィールド幅と同様、出力内容が指定桁数を超える場合、変化なし。

	指定例		       		出力結果	
printf("[%.0d]\n", 1234567);		[1234567]
printf("[%.5d]\n", 1234567);		[1234567]

出力内容が指定桁数に満たない場合、左側を0で埋める。 フィールド幅は(space)だったので注意。

-の場合、フィールド幅は指定桁数に-の一文字分を含むが、精度は-を指定桁数に含めない。

	指定例		       		出力結果	
printf("[%.10d]\n", 1234567);		[0001234567]
printf("[%.10d]\n", -1234567);		[-0001234567]

f, e, E変換の場合

小数点以下に表示する桁数を指定する。

出力内容が、指定桁数以上ある場合は切り捨てが発生する。

	指定例		       		出力結果	
printf("[%.0f]\n", 123.321);		[123]
printf("[%.0f]\n", 1234567.7654321);	[1234568]
printf("[%.5f]\n", 1234567.7654321);	[1234567.76543]

printf("[%.0e]\n", 123.321);		[1e+02]
printf("[%.0e]\n", 1234567.7654321);	[1e+06]
printf("[%.5e]\n", 1234567.7654321);	[1.23457e+06]

printf("[%.0E]\n", 123.321);		[1E+02]
printf("[%.0E]\n", 1234567.7654321);	[1E+06]
printf("[%.5E]\n", 1234567.7654321);	[1.23457E+06]

指定桁数が出力内容よりも大きい場合、0で埋める。

printf("[%.5f]\n", 123.321);		[-123.32100]
printf("[%.10f]\n", 123.321);		[123.3210000000]
printf("[%.10f]\n", -123.321);		[-123.3210000000]
printf("[%.10f]\n", 1234567.7654321);	[1234567.7654321000]	
printf("[%.10f]\n", -1234567.7654321);	[-1234567.7654321000]	

printf("[%.5e]\n", 123.321);		[1.23321e+02]
printf("[%.10e]\n", 123.321);		[1.2332100000e+02]
printf("[%.10e]\n", -123.321);		[-1.2332100000e+02]
printf("[%.10e]\n", 1234567.7654321);	[1.2345677654e+06]
printf("[%.10e]\n", -1234567.7654321);	[-1.2345677654e+06]

printf("[%.5E]\n", 123.321);		[1.23321E+02]
printf("[%.10E]\n", 123.321);		[1.2332100000E+02]
printf("[%.10E]\n", -123.321);		[-1.2332100000E+02]
printf("[%.10E]\n", 1234567.7654321);	[1.2345677654E+06]
printf("[%.10E]\n", -1234567.7654321);	[-1.2345677654E+06]

フィールド幅での変換指定子がf, e, Eの場合に、
小数点以下第6位まで自動的に表示されると述べたが、
これは「精度」がデフォルトで6になっているから。

printf("[%f]\n", 123.321);		[123.321000] 
printf("[%f]\n", 1234567.7654321);	[1234567.765432] → 最後の`1`が消えている。

gG変換の場合

有効数字の数を指定することになる。
小数点以下に表示する桁数を指定するわけではないので注意が必要。

こちらも出力内容が、指定桁数以上ある場合は切り捨てが発生する。

また、指定数が0の場合、1 と同じ出力結果になる。

	指定例		       		出力結果	
printf("[%.0g]\n", 123.321);		[1e+02]2つ下の`1`の場合と同じ出力
printf("[%.0G]\n", 123.321);		[1E+02]
printf("[%.1g]\n", 123.321);		[1e+02]
printf("[%.1G]\n", 123.321);		[1E+02]
printf("[%.2g]\n", 123.321);		[1.2e+02] →有効数字の数が`2`なので、`1`と`2`を出力
printf("[%.2G]\n", 123.321);		[1.2E+02]
printf("[%.3g]\n", 123.321);		[123]→有効数字の数が`3`なので、`1`,`2`,`3`を出力
printf("[%.3G]\n", 123.321);		[123]

有効桁数が出力内容よりも大きい場合、0で埋めないので注意が必要。

	指定例		       		出力結果	
printf("[%.10G]\n", 123.321);		[123.321]
printf("[%.10g]\n", -123.321);		[-123.321]
printf("[%.10G]\n", -123.321);		[-123.321]

上記の例を有効数を20にした場合は以下のように出力される。

これは、浮動小数点数の誤差が発生しており、英語では「floating-point imprecision」と言う。

	指定例		       		出力結果	
printf("[%.20g]\n", 123.321);		[123.32099999999999795]
printf("[%.20G]\n", 123.321);		[123.32099999999999795]
printf("[%.20g]\n", -123.321);		[-123.32099999999999795]
printf("[%.20G]\n", -123.321);		[-123.32099999999999795]

詳しくは説明しないが、わかりやすく解説してあるサイトのリンクを貼っておく。
https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html


文字列の場合

最大表示文字数を表し、数値以上の文字列は切り捨てられる。

	指定例		       		出力結果	
printf("[%.1s]\n", "apple");		[a]
printf("[%.3s]\n", "apple");		[app]

最大表示文字数が出力内容よりも多い場合は、最大表示文字数は無視される。

	指定例		       		出力結果	
printf("[%.10s]\n", "apple");		[apple]

その他

.(ピリオド)

.(ピリオド)のみで数値を省略した場合、「精度」として0を指定したのと同じ扱いとなる。

printf("[%.d]\n", 1234567);		[1234567]


*(アスタリスク)

*(アスタリスク)は、フィールド幅と同様、引数を使って数値を指定することを意味する。

上記の例を`*`を使用して書き直したサンプルコード
	指定例		       		出力結果		
// 整数の場合 (変換指定子が`d`や`o`など) 
printf("[%.*d]\n", 0, 1234567);			[1234567]
printf("[%.*d]\n", 5, 1234567);			[1234567]

printf("[%.*d]\n", 10, 1234567);		[0001234567]	
printf("[%.*d]\n", 10, -1234567);		[-0001234567]	

// 変換指定子が`f`, `e`, `E`の場合
printf("[%.*f]\n", 0, 123.321);			[123]
printf("[%.*f]\n", 0, 1234567.7654321);		[1234568] →四捨五入が発生
printf("[%.*f]\n", 5, 1234567.7654321);		[1234567.76543]

printf("[%.*e]\n", 0, 123.321);			[1e+02]
printf("[%.*e]\n", 0, 1234567.7654321);		[1e+06]
printf("[%.*e]\n", 5, 1234567.7654321);		[1.23457e+06]

printf("[%.*E]\n", 0, 123.321);			[1E+02]
printf("[%.*E]\n", 0, 1234567.7654321);		[1E+06]
printf("[%.*E]\n", 5, 1234567.7654321);		[1.23457E+06]

printf("[%.*f]\n", 5, 123.321);			[123.32100]
printf("[%.*f]\n", 10, 123.321);		[123.3210000000]
printf("[%.*f]\n", 10, -123.321);		[-123.3210000000]
printf("[%.*f]\n", 10, 1234567.7654321);	[1234567.7654321000]	
printf("[%.*f]\n", 10, -1234567.7654321);	[-1234567.7654321000]	
	
printf("[%.*e]\n", 5, 123.321);			[1.23321e+02]
printf("[%.*e]\n", 10, 123.321);		[1.2332100000e+02]
printf("[%.*e]\n", 10, -123.321);		[-1.2332100000e+02]
printf("[%.*e]\n", 10, 1234567.7654321);	[1.2345677654e+06]	
printf("[%.*e]\n", 10, -1234567.7654321);	[-1.2345677654e+06]	

printf("[%.*E]\n", 5, 123.321);			[1.23321E+02]
printf("[%.*E]\n", 10, 123.321);		[1.2332100000E+02]
printf("[%.*E]\n", 10, -123.321);		[-1.2332100000E+02]
printf("[%.*E]\n", 10, 1234567.7654321);	[1.2345677654E+06]	
printf("[%.*E]\n", 10, -1234567.7654321);	[-1.2345677654E+06]	

//変換指定子が`g`, `G`の場合
printf("[%.*g]\n", 0, 123.321);		[1e+02]
printf("[%.*G]\n", 0, 123.321);		[1E+02]
printf("[%.*g]\n", 1, 123.321);		[1e+02]
printf("[%.*G]\n", 1, 123.321);		[1E+02]
printf("[%.*g]\n", 2, 123.321);		[1.2e+02]
printf("[%.*G]\n", 2, 123.321);		[1.2E+02]
printf("[%.*g]\n", 3, 123.321);		[123]
printf("[%.*G]\n", 3, 123.321);		[123]

printf("[%.*g]\n", 10, 123.321);	[123.321]	
printf("[%.*G]\n", 10, 123.321);	[123.321]	
printf("[%.*g]\n", 10, -123.321);	[-123.321]	
printf("[%.*G]\n", 10,  -123.321);	[-123.321]	

printf("[%.*g]\n", 20, 123.321);	[123.32099999999999795]	
printf("[%.*g]\n", 20, 123.321);	[123.32099999999999795]	
printf("[%.*g]\n", 20, -123.321);	[-123.32099999999999795]	
printf("[%.*G]\n", 20, -123.321);	[-123.32099999999999795]	

printf("[%.*g]\n", 20, 1234567.7654321);	[1234567.7654321000446]	
printf("[%.*G]\n", 20,  1234567.7654321);	[1234567.7654321000446]	
printf("[%.*g]\n", 20, -1234567.7654321);	[-1234567.7654321000446]	
printf("[%.*G]\n", 20, -1234567.7654321);	[-1234567.7654321000446]	
		
//文字列の場合
printf("[%.*s]\n", 1, "apple");		[a]
printf("[%.*s]\n", 3, "apple");		[app]
printf("[%.*s]\n", 10, "apple");	[apple]	

精度0で0を出力した場合

精度0で0を出力した場合、何も表示されない。

	指定例		       	出力結果	
printf("[%.0d]\n", 0);			[]
***

精度のデフォルト値(整数の場合)

整数の場合、精度のデフォルト値(なにも指定しなかった場合の数値)は1

実際の桁数と同じだけ出力する場合はこの1が使うが、精度のデフォルト値が1なので明示的に指定する必要はない。


*を使って.を引数として撮る場合

コンパイルエラーが発生する。

printf("[%*d]\n", ., 1234567);    コンパイルエラー

サンプルコード

サンプルコード
#include <stdio.h>

int main(void)
{
// 整数の場合 (変換指定子が`d`や`o`など) 
	printf("[%d]\n", 1234567);
	printf("[%d]\n", -1234567);

	printf("[%.0d]\n", 1234567);
	printf("[%.5d]\n", 1234567);

	printf("[%.10d]\n", 1234567);
	printf("[%.10d]\n", -1234567);

// 変換指定子が`f`, `e`, `E`の場合
	printf("[%f]\n", 123.321);
	printf("[%f]\n", -123.321);
	printf("[%f]\n", 1234567.7654321);
	printf("[%f]\n", -1234567.7654321);

	printf("[%e]\n", 123.321);
	printf("[%e]\n", -123.321);
	printf("[%e]\n", 1234567.7654321);
	printf("[%e]\n", -1234567.7654321);

	printf("[%E]\n", 123.321);
	printf("[%E]\n", -123.321);
	printf("[%E]\n", 1234567.7654321);
	printf("[%E]\n", -1234567.7654321);

	printf("[%.0f]\n", 123.321);
	printf("[%.0f]\n", 1234567.7654321);
	printf("[%.5f]\n", 1234567.7654321);

	printf("[%.0e]\n", 123.321);
	printf("[%.0e]\n", 1234567.7654321);
	printf("[%.5e]\n", 1234567.7654321);

	printf("[%.0E]\n", 123.321);
	printf("[%.0E]\n", 1234567.7654321);
	printf("[%.5E]\n", 1234567.7654321);

	printf("[%.5f]\n", 123.321);
	printf("[%.10f]\n", 123.321);
	printf("[%.10f]\n", -123.321);
	printf("[%.10f]\n", 1234567.7654321);
	printf("[%.10f]\n", -1234567.7654321);

	printf("[%.5e]\n", 123.321);
	printf("[%.10e]\n", 123.321);
	printf("[%.10e]\n", -123.321);
	printf("[%.10e]\n", 1234567.7654321);
	printf("[%.10e]\n", -1234567.7654321);

	printf("[%.5E]\n", 123.321);
	printf("[%.10E]\n", 123.321);
	printf("[%.10E]\n", -123.321);
	printf("[%.10E]\n", 1234567.7654321);
	printf("[%.10E]\n", -1234567.7654321);

//変換指定子が`g`, `G`の場合
	printf("[%g]\n", 123.321);
	printf("[%G]\n", 123.321);
	printf("[%g]\n", -123.321);
	printf("[%G]\n", -123.321);

	printf("[%.0g]\n", 123.321);
	printf("[%.0G]\n", 123.321);
	printf("[%.1g]\n", 123.321);
	printf("[%.1G]\n", 123.321);
	printf("[%.2g]\n", 123.321);
	printf("[%.2G]\n", 123.321);
	printf("[%.3g]\n", 123.321);
	printf("[%.3G]\n", 123.321);
	printf("[%.4g]\n", 123.321);
	printf("[%.4G]\n", 123.321);
	printf("[%.5g]\n", 123.321);
	printf("[%.5G]\n", 123.321);
	printf("[%.6g]\n", 123.321);
	printf("[%.6G]\n", 123.321);


	printf("[%.10g]\n", 123.321);
	printf("[%.10G]\n", 123.321);
	printf("[%.10g]\n", -123.321);
	printf("[%.10G]\n", -123.321);

	printf("[%.20g]\n", 123.321);
	printf("[%.20G]\n", 123.321);
	printf("[%.20g]\n", -123.321);
	printf("[%.20G]\n", -123.321);

	printf("[%.20g]\n", 1234567.7654321);
	printf("[%.20G]\n", 1234567.7654321);
	printf("[%.20g]\n", -1234567.7654321);
	printf("[%.20G]\n", -1234567.7654321);
//文字列の場合
	printf("[%.1s]\n", "apple");
	printf("[%.3s]\n", "apple");
	printf("[%.10s]\n", "apple");

//'.'を使用したケース
printf("[%.d]\n", 1234567);

	//以下'*'の場合
// 整数の場合 (変換指定子が`d`や`o`など) 
	printf("[%.*d]\n", 0, 1234567);
	printf("[%.*d]\n", 5, 1234567);

	printf("[%.*d]\n", 10, 1234567);
	printf("[%.*d]\n", 10, -1234567);

// 変換指定子が`f`, `e`, `E`の場合
	printf("[%.*f]\n", 0, 123.321);
	printf("[%.*f]\n", 0, 1234567.7654321);
	printf("[%.*f]\n", 5, 1234567.7654321);

	printf("[%.*e]\n", 0, 123.321);
	printf("[%.*e]\n", 0, 1234567.7654321);
	printf("[%.*e]\n", 5, 1234567.7654321);

	printf("[%.*E]\n", 0, 123.321);
	printf("[%.*E]\n", 0, 1234567.7654321);
	printf("[%.*E]\n", 5, 1234567.7654321);

	printf("[%.*f]\n", 5, 123.321);
	printf("[%.*f]\n", 10, 123.321);
	printf("[%.*f]\n", 10, -123.321);
	printf("[%.*f]\n", 10, 1234567.7654321);
	printf("[%.*f]\n", 10, -1234567.7654321);

	printf("[%.*e]\n", 5, 123.321);
	printf("[%.*e]\n", 10, 123.321);
	printf("[%.*e]\n", 10, -123.321);
	printf("[%.*e]\n", 10, 1234567.7654321);
	printf("[%.*e]\n", 10, -1234567.7654321);

	printf("[%.*E]\n", 5, 123.321);
	printf("[%.*E]\n", 10, 123.321);
	printf("[%.*E]\n", 10, -123.321);
	printf("[%.*E]\n", 10, 1234567.7654321);
	printf("[%.*E]\n", 10, -1234567.7654321);

//変換指定子が`g`, `G`の場合
	printf("[%.*g]\n", 0, 123.321);
	printf("[%.*G]\n", 0, 123.321);
	printf("[%.*g]\n", 1, 123.321);
	printf("[%.*G]\n", 1, 123.321);
	printf("[%.*g]\n", 2, 123.321);
	printf("[%.*G]\n", 2, 123.321);
	printf("[%.*g]\n", 3, 123.321);
	printf("[%.*G]\n", 3, 123.321);
	printf("[%.*g]\n", 4, 123.321);
	printf("[%.*G]\n", 4, 123.321);
	printf("[%.*g]\n", 5, 123.321);
	printf("[%.*G]\n", 5, 123.321);
	printf("[%.*g]\n", 6, 123.321);
	printf("[%.*G]\n", 6, 123.321);

	printf("[%.*g]\n", 10, 123.321);
	printf("[%.*G]\n", 10, 123.321);
	printf("[%.*g]\n", 10, -123.321);
	printf("[%.*G]\n", 10,  -123.321);

	printf("[%.*g]\n", 20, 123.321);
	printf("[%.*g]\n", 20, 123.321);
	printf("[%.*g]\n", 20, -123.321);
	printf("[%.*G]\n", 20, -123.321);

	printf("[%.*g]\n", 20, 1234567.7654321);
	printf("[%.*G]\n", 20,  1234567.7654321);
	printf("[%.*g]\n", 20, -1234567.7654321);
	printf("[%.*G]\n", 20, -1234567.7654321);
//文字列の場合
	printf("[%.*s]\n", 1, "apple");
	printf("[%.*s]\n", 3, "apple");
	printf("[%.*s]\n", 10, "apple");
//精度0で0を出力した場合
	printf("[%.0d]\n", 0);
	return (0);
}

フィールド値と精度の併用

サンプルコード
#include <stdio.h>

int main(void)
{
	printf("[%0.1d]\n", 10);
	printf("[%0.5d]\n", 10);
	printf("[%10.1d]\n", 10);
	printf("[%10.5d]\n", 10);

	printf("[%0.1f]\n", 123.321);
	printf("[%0.5f]\n", 123.321);
	printf("[%10.1f]\n", 123.321);
	printf("[%10.5f]\n", 123.321);

	printf("[%0.1e]\n", 123.321);
	printf("[%0.5e]\n", 123.321);
	printf("[%10.1e]\n", 123.321);
	printf("[%10.5e]\n", 123.321);

//	printf("[%0.1s]\n", "123.321");  //コンパイルエラー
//	printf("[%0.5s]\n", "123.321");    //コンパイルエラー
	printf("[%10.1s]\n", "123.321");
	printf("[%10.5s]\n", "123.321");

}


長さ修飾子

長さ修飾子は実引数のデータ型のサイズを指定する。

長さ修飾子は省略可能。

修飾子 意味
hh 実引数は char 型
h 実引数は short 型
l 実引数は long 型または wchar_t 型または double 型
ll 実引数は long long 型
j 実引数は intmax_t 型
z 実引数は size_t 型
t 実引数は ptrdiff_t 型
L 実引数は long double 型

変換指定子の種類

指定子 対応する型 説明
c char 文字
s char * 文字列
d, i int, short 10進の整数
u unsigned int, unsigned short 10進の符号なし整数
o int, short, unsigned int, unsigned short 8進の整数
x, X int, short, unsigned int, unsigned short 16進の整数
f, F float 浮動小数点数
e, E float 浮動小数点数の指数表示
g, G float %eもしくは%fのどちらか最適な形式の浮動小数点数
ld long 10進の倍精度整数
lu unsinged long 10進の符号なし倍精度整数
lo long, unsinged long 8進の倍精度整数
lx long, unsinged long 16進の倍精度整数
lf double 倍精度浮動小数点数
a, A double 16進の倍精度浮動小数点数
% char %を出力

指数表示

大きな数または非常に小さな数を表記するのに便利な、数の表記方法の1つ。

いろいろな表示方法があり、12345を例にすると以下3通りがある。

12345
= 1.2345 × 10^{4}
= 1.2345E+4
= 1.2345e+4

2行目が数学で使用される表示方法。
3行目は電卓の表示法で10の巾乗を大文字のEで表現。
4行目がC言語で一般的な表記で小文字のeを使用。大文字のEも使うことができるが、小文字の方が一般的。


参考ウェブサイト

https://www.mm2d.net/main/prog/c/printf_format-03.html

https://www.cplusplus.com/reference/cstdio/printf/

Discussion