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以上:転送バイト数
負   :失敗
関数返却値
①転送されたバイト数を返します。
②出力エラーあるいは、表現形式エラーが発生した場合は、負の値を返します。

処理系限界  変換によって生成される最大の文字数の最低値は 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  プライバシーポリシー