printf関数【C言語辞典】HIR-NET

HIR-NET Home 運営者 オンラインソフト 運営者著書 CG HIR-NETリンク集 (追記) (追記ここまで)
Tweet このエントリーをはてなブックマークに追加
C言語辞典

printfプリント・エフ関数かんすう
printf function

語源 printプリント formatーマッツ(書式印字)
分類 C/C++標準ライブラリ/関数/入出力関数/出力関数/書式出力関数
名称 書式表示関数(format display function)
対義 scanf関数
同等 wprintf関数
類似 vprintf関数, vfprintf関数
関連 sprintf関数
解説 printf関数は、数値を書式変換し表示する関数です。第1引数が、stdout である fprintf関数と等価です。出力のための変換方法を示す出力書式文字列*format... の制御のもとに続く実引数を変換し、標準出力ストリームに出力します。
書式に対し、十分な実引数がない場合の動作は未定義です。実引数が残っている間に書式が尽きてしまう場合は余分の実引数は通常の評価はされますが出力には関係しません。
*format... の終わりに達したとき、printf関数は終了します。%以外の単/多バイト文字は変換されることなく、そのまま出力ストームに複写され、出力変換仕様は それぞれ 0個以上の後続の実引数を取り出します。

関数原型宣言ヘッダ <stdio.h>
関数原型宣言例
 出力書式文字列 可変個引数
 ↓ ↓
int printf(const char *restrict format,...);
↓
0以上:転送バイト数
負 :失敗
関数返却値
1転送されたバイト数を返します。
2出力エラーあるいは、表現形式エラーが発生した場合は、負の値を返します。

処理系限界 変換によって生成される最大の文字数の最低値は 509バイト以上です。
落とし穴1 puts関数を printf関数に置き換えるのは避けるべきです。なぜなら puts関数の文字列は無変換で出力されますが、printf関数の書式文字列は % が特別な意味を持つからですあ。これを忘れると思わぬバグに遭遇することになります。次の 3つの違いに注意してください。
 puts("%%"); ...... %を2つ出力
 printf("%%\n"); ...... %を1つ出力
 printf("%s\n","%%"); ...... %を2つ出力
落とし穴2 printf関数を使用したにも関わらず何も表示されないというは、
 printf("%d\n",123);
のつもりで
 ("%d\n",123);
としてしまっている場合もあります。まさかそんなことと思うかも知れませんが、C/C++ では文字列も式として成り立ってしまうため、誤りの発見が遅れるわけです。

関数定義例
// printf.c
#include <stdio.h> // FILE,stdout,vfprintf
#include <stdarg.h> // va_list,va_start,va_end
int printf( // 書式表示関数 PRINT Format
// 0以上:転送バイト数
// 負 :失敗
const char *format, // 出力書式文字列
 ...) // 可変個引数
{
 int r; // 返却値
 va_list args; // 作業用変数の定義
 va_start(args,format); // 初期化
 r=vfprintf(stdout,format,args);
 va_end(args); // 終了
 return r;
} // printf
(追記) (追記ここまで)

プログラム例 だいやまーく さんかく

出力変換仕様の使い方
// ocs1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
#include <limits.h> // UINT_MAX
int main(void)
{
 int i=123;
 int n; // n変換用
 unsigned u=UINT_MAX;
 long int l=12345678;
 long int li=i;
 char *s="ABCDEFG";
 printf(s); // 文字列リテラルでなくてもよい
 printf("[改行しない]");
 printf("[\n]");
 printf("[\\nで改行]\n");
 printf("[0円以降は出力されない\n]"); // '0円'を出力するにはc変換を使う
 printf("\n");
 printf("[%i]\n",i); // [123] dとiは同じ
 printf("[%d]\n",i); // [123] 変換指定子のみ
 printf("[%d]\n",li); // [123] 値がintの範囲ならばlong型でも可
 printf("[%d]\n",u); // [-1] (処理系依存)
 printf("[%u]\n",u); // [65535] u変換(65535は処理系依存)
 printf("[%5d]\n",i); // [ 123] 最小フィールド幅
 printf("[%.5d]\n",i); // [00123] 精度
 printf("[%05d]\n",i); // [00123] 0フラグ
 printf("[%0*d]\n",5,i); // [00123] 0フラグ+*最小フィールド幅
 printf("[%-5d]\n",i); // [123 ] 左詰めフラグ
 printf("[%d]\n" ,-i); // [-123] 負値
 printf("[%+d]\n", i); // [+123] 符号フラグ
 printf("[% d]\n", i); // [ 123] 空白フラグ
 printf("[% d]\n",-i); // [-123] 空白フラグ
 printf("[%+06d]\n",i); // [+00123] 符号フラグ+0フラグ
 printf("[%.0d]\n",0); // [] 精度0
 printf("[%*d]\n",4,i); // [ 123] *最小フィールド幅
 printf("[%.*d]\n",4,i); // [0123] *精度
 printf("[%ld]\n",l); //[12345678] long修飾
 printf("[%%]\n"); // [%] %変換
 printf("[abc[%n]]\n",&n); // [abc[]] n変換
 i=printf("[%d]\n",n); // [5]
 printf("[%d]\n",i); // [4]
 printf("[%s|%d]\n",s,i); //[DEFG|4] 複合例
 return EXIT_SUCCESS;
} // main
実行結果
ABCDEFG[改行しない][
][\nで改行]
[ ...... 0円以降は出力されていない
[123]
[123]
[123]
[-1]
[65535]
[ 123]
[00123]
[00123]
[00123]
[123 ]
[-123]
[+123]
[ 123]
[-123]
[+00123]
[]
[ 123]
[0123]
[12345678]
[%]
[abc[]]
[5] ...... 上の結果
[4]
[ABCDEFG|4]


(追記) (追記ここまで)

10進・8進・16進変換の使い方
// ocs_x1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 int i=123;
 printf("[%d]\n",i); // [123] d変換
 printf("[%o]\n",i); // [173] o変換
 printf("[%x]\n",i); // [7b] x変換
 printf("[%X]\n",i); // [7B] X変換
 printf("[%#x]\n",i); // [0x7b] 表記x変換
 printf("[%#X]\n",i); // [0X7B] 表記X変換
 printf("[%#04x]\n",1); // [0x01] 表記0フラグx変換
 printf("[%#04x]\n",0); // [0000] 表記0フラグx変換
 return EXIT_SUCCESS;
} // main
実行結果 小文字と大文字に注意。
[123]
[173]
[7b]
[7B]
[0x7b]
[0X7B]
[0x01]
[0000]


実数の出力変換仕様の使い方
// ocs_f1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
#include <float.h> // LDBL_DIG
int main(void)
{
 double e5=1.234e-5;
 float f=1234.5123451234512345F;
 double fd=1234.5123451234512345;
 long double fld=1234.5123451234512345L;
 printf("[%f]\n",fd); // [1234.512345] f変換
 printf("[%f]\n",f); // [1234.512329] floatでも可
 printf("[%f]\n",fld); // [-0.000000] long doubleは不可(型があわず不定)
 printf("[%Lf]\n",fld); // [1234.512345] long double 修飾
 printf("[%f]\n",0.1234); // [0.123400] (語尾の0は残る)
 printf("[%f]\n",-DBL_EPSILON); // [-0.000000] (0でない負を示す)
 printf("[%.9f]\n",fd); // [1234.512345123]
 printf("[%.5f]\n",fd); // [1234.51235] (四捨五入されている)
 printf("[%.4f]\n",fd); // [1234.5123]
 printf("[%11.3f]\n",fd); // [ 1234.512]
 printf("[%2.3f]\n",fd); // [1234.512] (フィールド足りず)
 printf("[%9.3f]\n",+fd); // [ 1234.512]
 printf("[%9.3f]\n",-fd); // [-1234.512]
 printf("[% .3f]\n",+fd); // [ 1234.512] フィールドに頼らず空白フラグ使用
 printf("[% .3f]\n",-fd); // [-1234.512]
 printf("[%e]\n",fd); // [1.234512e+03] e変換
 printf("[%E]\n",fd); // [1.234512E+03] E変換
 printf("[%E]\n",0.); // [0.000000E+00] (値0.)
 printf("[%E]\n",0); // [-1.843997E+306] (0はintであり、型があわず不定)
 printf("[%.*Lf]\n",LDBL_DIG-4,fld); // [1234.51234512345123](LDBL_DIGは処理系依存)
 printf("[%g]\n",e5); // [1.234e-05] g変換
 printf("[%G]\n",e5); // [1.234E-05] G変換
 printf("[%G]\n",fd); // [1234.51]
 printf("[%10G]\n",fd); // [ 1234.51]
 printf("[%+010G]\n",fd); // [+001234.51]
 return EXIT_SUCCESS;
} // main
実行結果
[1234.512345]
[1234.512329]
[-0.000000]
[1234.512345]
[0.123400]
[-0.000000]
[1234.512345123]
[1234.51235]
[1234.5123]
[ 1234.512]
[1234.512]
[ 1234.512]
[-1234.512]
[ 1234.512]
[-1234.512]
[1.234512e+03]
[1.234512E+03]
[0.000000E+00]
[1.426423E+179]
[1234.512345123451230]
[1.234e-05]
[1.234E-05]
[1234.51]
[ 1234.51]
[+001234.51]


%c変換の使い方
// ocs_c1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 char c='A';
 printf("[%c]\n",c); // [A] c変換
 printf("[%c]\n",0); // [ ] (空文字も出力される)
 return EXIT_SUCCESS;
} // main
実行結果 一例を示す。[ ]は[と]の間には空文字('0円')が出力されている。ASCII ならば 5B 00 5D 0A というコードが並ぶ。
[A]
[ ]


%s変換の使い方
// ocs_s1.c
#include <stdio.h> // NULL,printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 char *s="ABCDEFG";
 // 文字列リテラルへのポインタ
 char *format="[%s]\n";
 printf("[%s]\n",s); // [ABCDEFG] s変換
 printf(format,s); // [ABCDEFG] formatもポインタ
 printf("[%.2s]\n",s); // [AB]精度で制限可能
 printf("[%2s]\n",s); // [ABCDEFG]最小フィールド幅
 printf("[%10s]\n",s); // [ ABCDEFG]右詰め
 printf("[%-10s]\n",s); // [ABCDEFG ]左詰め
 printf("[%9.5s]\n",s); // [ ABCDE]
 printf("[%-9.5s]\n",s); // [ABCDE ]
 printf("[%s]\n",s+2); // [CDEFG] ポインタを進める
 s[0]='0円'; // 最初の文字が空文字
 printf("[%s]\n",s); // [] 0個の文字になる
 s=NULL; // 空ポインタ
 printf("[%s]\n",s); // [(null)] (null)は処理系依存
 return EXIT_SUCCESS;
} // main
実行結果 一例を示す。
[ABCDEFG]
[ABCDEFG]
[AB]
[ABCDEFG]
[ ABCDEFG]
[ABCDEFG ]
[CDEFG]
[]
[(null)] ...... 処理系依存


ポインタの出力変換仕様の使い方
%p の形式は処理系定義である。
// ocs_p1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 char *s="ABCDEFG"; // 文字列リテラルへのポインタ
 printf("[%p|%s]\n",s,s++); // p変換(形式は処理系依存)
 printf("[%p|%s]\n",s,s++); // ポインタを進めている
 printf("[%p|%s]\n",s,s++); // ポインタを進めている
 return EXIT_SUCCESS;
} // main
実行結果 一例を示す。
[5BB7:0169|ABCDEFG]
[5BB7:016A|BCDEFG]
[5BB7:016B|CDEFG]


(追記) (追記ここまで)

%G変換の使い方
// ocs_g1.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 printf("[%G]\n",0.1234); //[0.1234] (語尾の0は残らない)
 printf("[%G]\n",0.12345); //[0.12345] (語尾の0は残らない)
 printf("[%G]\n",0.123456); //[0.123456] (語尾の0は残らない)
 printf("[%G]\n",0.1234567); //[0.123457] (6桁目四捨五入)
 puts("");
 printf("[%.4G]\n",0.0123456789); //[0.01235] (4桁目四捨五入)
 printf("[%.4G]\n",0.0123449999); //[0.01234]
 puts("");
 printf("[%G]\n",1234567.); //[1.23457E+06] 精度6 (6桁目四捨五入)
 printf("[%G]\n",123456.7); //[123457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",12345.67); //[12345.7] 精度6 (6桁目四捨五入)
 printf("[%G]\n",1234.567); //[1234.57] 精度6 (6桁目四捨五入)
 printf("[%G]\n",123.4567); //[123.457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",12.34567); //[12.3457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",1.234567); //[1.23457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",0.1234567); //[0.123457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",0.01234567); //[0.0123457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",0.001234567); //[0.00123457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",0.0001234567); //[0.000123457] 精度6 (6桁目四捨五入)
 printf("[%G]\n",0.00001234567); //[1.23457E-05] 精度6 (6桁目四捨五入)
 puts("");
 printf("[%.5G]\n",123456.); //[1.2346+E05] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",12345.6); //[12346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",1234.56); //[1234.6] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",123.456); //[123.46] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",12.3456); //[12.346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",1.23456); //[1.2346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",0.123456); //[0.12346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",0.0123456); //[0.012346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",0.00123456); //[0.0012346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",0.000123456); //[0.00012346] 精度5 (5桁目四捨五入)
 printf("[%.5G]\n",0.0000123456); //[1.2346E-05] 精度5 (5桁目四捨五入)
 puts("");
 printf("[%.5G]\n",456.); //[456] 精度5 (四捨五入なし)
 printf("[%.5G]\n",45.6); //[45.6] 精度5 (四捨五入なし)
 printf("[%.5G]\n",4.56); //[4.56] 精度5 (四捨五入なし)
 printf("[%.5G]\n",0.456); //[0.456] 精度5 (四捨五入なし)
 printf("[%.5G]\n",0.0456); //[0.0456] 精度5 (四捨五入なし)
 printf("[%.5G]\n",0.00456); //[0.00456] 精度5 (四捨五入なし)
 printf("[%.5G]\n",0.000456); //[0.000456] 精度5 (四捨五入なし)
 printf("[%.5G]\n",0.0000456); //[4.56E-05] 精度5 (四捨五入なし)
 return EXIT_SUCCESS;
} // main
実行結果
[0.1234]
[0.12345]
[0.123456]
[0.123457]
[0.01235]
[0.01234]
[1.23457E+06]
[123457]
[12345.7]
[1234.57]
[123.457]
[12.3457]
[1.23457]
[0.123457]
[0.0123457]
[0.00123457]
[0.000123457]
[1.23457E-05]
[1.2346E+05]
[12346]
[1234.6]
[123.46]
[12.346]
[1.2346]
[0.12346]
[0.012346]
[0.0012346]
[0.00012346]
[1.2346E-05]
[456]
[45.6]
[4.56]
[0.456]
[0.0456]
[0.00456]
[0.000456]
[4.56E-05]


%G変換指数表示切替
%G変換で、指数表示に切り替わることの検証。
// ocs_g2.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 printf("[%G]\n",1000000.); //[1E+06]
 printf("[%G]\n",100000.); //[100000]
 printf("[%G]\n",10000.); //[10000]
 printf("[%G]\n",1000.); //[1000]
 printf("[%G]\n",100.); //[100]
 printf("[%G]\n",10.); //[10]
 printf("[%G]\n",1.); //[1]
 printf("[%G]\n",0.1); //[0.1]
 printf("[%G]\n",0.01); //[0.01]
 printf("[%G]\n",0.001); //[0.001]
 printf("[%G]\n",0.0001); //[0.0001]
 printf("[%G]\n",0.00001); //[1E-05]
 printf("[%G]\n",0.000001); //[1E-06]
 return EXIT_SUCCESS;
} // main
実行結果
[1E+06]
[100000]
[10000]
[1000]
[100]
[10]
[1]
[0.1]
[0.01]
[0.001]
[0.0001]
[1E-05]
[1E-06]


%G変換の丸めの状況
// ocs_g3.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 // 精度1 (1桁目四捨五入)
 printf("[%.1G]\n",1.3); // [1]
 printf("[%.1G]\n",1.4); // [1]
 printf("[%.1G]\n",1.5); // [2]
 printf("[%.1G]\n",1.6); // [2]
 return EXIT_SUCCESS;
} // main
実行結果
[1]
[1]
[2]
[2]


%G変換の問題点
浮動小数点の精度上の問題で四捨五入が数学どおりにいかないことがある。
// ocs_g4.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 // 精度3
 printf("[%.3G]\n",1005.);
 printf("[%.3G]\n",100.5);
 printf("[%.3G]\n",10.05);
 printf("[%.3G]\n",1.005);
 printf("[%.3G]\n",0.1005);
 printf("[%.3G]\n",0.01005);
 printf("[%.3G]\n",0.001005);
 printf("[%.3G]\n",0.0001005);
 printf("[%.3G]\n",0.00001005);
 puts(""); // 精度2
 printf("[%.2G]\n",105.);
 printf("[%.2G]\n",10.5);
 printf("[%.2G]\n",1.05);
 printf("[%.2G]\n",0.105);
 printf("[%.2G]\n",0.0105);
 printf("[%.2G]\n",0.00105);
 printf("[%.2G]\n",0.000105);
 printf("[%.2G]\n",0.0000105);
 puts(""); // 精度1
 printf("[%.1G]\n",15.);
 printf("[%.1G]\n",1.5);
 printf("[%.1G]\n",0.15);
 printf("[%.1G]\n",0.015);
 printf("[%.1G]\n",0.0015);
 printf("[%.1G]\n",0.00015);
 printf("[%.1G]\n",0.000015);
 return EXIT_SUCCESS;
} // main
実行結果
[1E+03] ...... 1.01E+03 が正しい
[100] ...... 101 が正しい
[10.1] ...... 正常
[1] ...... 1.01 が正しい
[0.101] ...... 正常
[0.01] ...... 0.0101 が正しい
[0.00101] ...... 正常
[0.000101] ...... 正常
[1.01E-05] ...... 正常
[1E+02] ...... 1.1E+02 が正しい
[10] ...... 11 が正しい
[1.1] ...... 正常
[0.1] ...... 0.11 が正しい
[0.011] ...... 正常
[0.001] ...... 0.0011 が正しい
[0.00011] ...... 正常
[1E-05] ...... 1.1E-05 が正しい
[2E+01] ...... 正常
[2] ...... 正常
[0.1] ...... 0.2 が正しい
[0.01] ...... 0.02 が正しい
[0.002] ...... 正常
[0.0001] ...... 0.0002 が正しい
[2E-05] ...... 正常


%G変換の検証
前のプログラムの最後の桁の値を6にした。結果として四捨六入五不定になっていることが分かる。
// ocs_g5.c
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
int main(void)
{
 // 精度3
 printf("[%.3G]\n",1006.);
 printf("[%.3G]\n",100.6);
 printf("[%.3G]\n",10.06);
 printf("[%.3G]\n",1.006);
 printf("[%.3G]\n",0.1006);
 printf("[%.3G]\n",0.01006);
 printf("[%.3G]\n",0.001006);
 printf("[%.3G]\n",0.0001006);
 printf("[%.3G]\n",0.00001006);
 puts(""); // 精度2
 printf("[%.2G]\n",106.);
 printf("[%.2G]\n",10.6);
 printf("[%.2G]\n",1.06);
 printf("[%.2G]\n",0.106);
 printf("[%.2G]\n",0.0106);
 printf("[%.2G]\n",0.00106);
 printf("[%.2G]\n",0.000106);
 printf("[%.2G]\n",0.0000106);
 puts(""); // 精度1
 printf("[%.1G]\n",16.);
 printf("[%.1G]\n",1.6);
 printf("[%.1G]\n",0.16);
 printf("[%.1G]\n",0.016);
 printf("[%.1G]\n",0.0016);
 printf("[%.1G]\n",0.00016);
 printf("[%.1G]\n",0.000016);
 return EXIT_SUCCESS;
} // main
実行結果 すべて正常。
[1.01E+03]
[101]
[10.1]
[1.01]
[0.101]
[0.0101]
[0.00101]
[0.000101]
[1.01E-05]
[1.1E+02]
[11]
[1.1]
[0.11]
[0.011]
[0.0011]
[0.00011]
[1.1E-05]
[2E+01]
[2]
[0.2]
[0.02]
[0.002]
[0.0002]
[2E-05]

(追記) (追記ここまで)



HIR-NET Home 運営者 オンラインソフト 運営者著書 CG HIR-NETリンク集
だいやまーくリンクは、ご自由にお張りください。

Copyright © 1988-2017 Hirabayashi Masahide プライバシーポリシー

AltStyle によって変換されたページ (->オリジナル) /