C言語のprintfの簡単な使い方: フォーマット文字列と引数

93, 2020-10-28

目次

printf関数の使い方

C言語の標準ライブラリにはstdio.hというライブラリがあります。
このライブラリに「printf関数」という関数があります。

printf関数は文字列や変数の中身などを画面に出力したい時に使われる関数です。
PHPではecho, Pythonではprint, Rubyではputs的なポジションの関数です。

このprintf関数はC言語を扱う場合、非常に基本的な関数ですが、その仕様について理解している人はあまり多くありません。
身近過ぎてprintf()について勉強する気にならないんですね、たぶん。
かく言う私もそうだったのでこの記事にまとめてみました。

この記事ではprintf()の基本的な使い方を解説します。

printf関数の構造

printf()は↓のような構造を持ちます。

int printf(const char *format, ...);

printf()int型の返り値を返し、第1引数にフォーマット文字列、第2引数以降にフォーマット文字列への可変長引数を取ります。
また、printf()を使用するにはstdio.hをインクルードする必要があります。

format(第1引数)

formatはフォーマット文字列ですが、これは言い換えると「printf書式指定子が使える文字列」となります。
書式指定子とは、変数の出力方法の指定です。
たとえばchar型の変数を指定したい場合は%cという指定子、int型の整数を出力したい場合は%dという指定子、と言う風にデータの型によって使い分けます。

以下は代表的な書式指定子です。

  • %c ... 文字(char)を出力する

  • %s ... 文字列(char , const char )を出力する

  • %d ... 整数(int, short)を出力する

  • %u ... 符号なし整数(unsigned int)を出力する

  • %o ... 整数を8進数として出力する

  • %x ... 整数を16進数として出力する

  • %f ... 実数(float)を出力する

  • %lf ... 実数(double)を出力する

formatにはこれらの書式指定子と、普通の文字列を混合させて書くことが出来ます。
たとえば↓のようにです。

"私の名前は %s"
"私の年齢は %d, あなたの年齢は %u"

第1引数のformatに書式指定子を使うとprintf()は第2引数以降の引数を解析して、フォーマットの指定子に従った出力をしようとします。
たとえば↓のような場合、

printf("こんにちは %s, 私の戦闘力は %d 万です。", "太朗", 400);

指定子の%sには第2引数の"太朗"が割り当てられ、指定子の%dには第3引数の400が割り当てられます。

可変長引数(第2引数以降)

...」というのはC言語では珍しいですが、これは可変長引数を表すキーワードです。
この引数は固定された長さを持たず、いくつも引数を渡すことが出来ます。
たとえば↓のようにです。

printf("\n");
printf("%d\n", 10);
printf("%d %f\n", 10, 3.14);
printf("%d %f %s\n", 10, 3.14, "Tanaka");

可変長引数は省略することも出来ます。つまりこの「...」に引数は必須でありません。

返り値

printf()の返り値は出力した文字数です。
これはint型の整数です。

stdio.hのインクルード

C言語でprintf()を使うにはまず最初にstdio.hをインクルードしなければなりません。
↓のようにインクルードを行います。

#include <stdio.h>

int
main(void) {
    return 0;
}

ついでにmain関数も書いておきます。
これをgccなどのコンパイラでコンパイルすると何もしないプログラムが作成されます。

> gcc sample.c

stdio.hの中ではprintf()はどのように書かれているのでしょうか?
これは使っているコンパイラによって内容が変わりますが、筆者のMinGWのGCCコンパイラでは↓のようになっていました。

__mingw_ovr
__attribute__((__format__ (gnu_printf, 1, 2))) __MINGW_ATTRIB_NONNULL(1)
int printf (const char *__format, ...)
{
  register int __retval;
  __builtin_va_list __local_argv; __builtin_va_start( __local_argv, __format );
  __retval = __mingw_vprintf( __format, __local_argv );
  __builtin_va_end( __local_argv );
  return __retval;
}

ヘッダファイルに直接定義が書かれていますね。

文字列の出力

printf()で文字列を出力するには↓のようにprintf()の第1引数に文字列を渡します。

#include <stdio.h>

int
main(void) {
    printf("Hello, World!\n");
    return 0;
}

printf()は出力するときに文字列の末尾に改行を付けません。
そのため改行させたい場合は↑のように文字列の末尾に改行を付けます。

可変長引数を使った出力

printf()の本領を発揮できるフォーマット文字列と可変長引数を使った出力です。

#include <stdio.h>

int
main(void) {
    int a = 10;
    float b = 3.14;
    const char *c = "Gokigen";

    printf("a = %d, b = %f, c = %s\n", a, b, c);

    return 0;
}

↑のコードをコンパイルすると↓のような出力になります。

a = 10, b = 3.140000, c = Gokigen

桁数の指定

指定子には表示桁数を指定することが出来ます。
これは全体の幅.小数点以下の幅あるいは全体の桁数で指定します。
↓の例ではわかりやすくするために[]で囲っていますが、この角カッコは必須ではありません。

#include <stdio.h>

int
main(void) {
    printf("[%4.2f]\n", 3.1412);
    printf("[%10s]\n", "Hi Taro");
    printf("[%.4s]\n", "Hi Miho");
    return 0;
}

出力結果↓。

[3.14]
[   Hi Taro]
[Hi M]

ゼロ詰めをする

指定子に0を加えることで0埋めが可能です。

#include <stdio.h>

int
main(void) {
    printf("[%08.2f]\n", 3.1412);
    printf("[%010s]\n", "Hi Taro");
    return 0;
}

出力結果↓。

[00003.14]
[000Hi Taro]

左詰めにする

全体を左詰めにしたい場合は-を加えます。

#include <stdio.h>

int
main(void) {
    printf("[%-8.2f]\n", 3.1412);
    printf("[%-10s]\n", "Hi Taro");
    return 0;
}

出力結果↓。

[3.14    ]
[Hi Taro   ]

プラスの符号を出力する

正の整数の符号はデフォルトでは出力されませんが、+を付けると出力されるようになります。

#include <stdio.h>

int
main(void) {
    printf("[%+8.2f]\n", 3.1412);
    return 0;
}

出力結果↓。

[   +3.14]

おわりに

printf()は意外と奥の深い関数ですが、使えるようになると便利な関数です。
またfprintf()sprintf()などのファミリーも多いので、これを使えるようになっておくと色々な場面で役に立つと言えます。

参考

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。