Namespaces
Variants

std::scanf, std::fscanf, std::sscanf

ja.cppreference.net より
< C++ | io | c
 
 
 
C 形式 I/O
型とオブジェクト
関数
ファイルアクセス
直接入出力
書式なし入出力
書式付き入力
(C++11)(C++11)(C++11)    
(C++11)(C++11)(C++11)    
 
ヘッダ <cstdio>
int scanf( const char* format, ... );
で定義 (1)
int fscanf( std::FILE* stream, const char* format, ... );
(2)
int sscanf( const char* buffer, const char* format, ... );
(3)

様々なソースからデータを読み取り、format に従って解釈し、結果を指定された場所に格納します。

1) stdin からデータを読み取ります。
2) ファイルストリーム stream からデータを読み取ります。
3) ヌル終端文字列 buffer からデータを読み取ります。

パラメータ

stream - 読み取り元の入力ファイルストリーム
buffer - 読み取り元のヌル終端文字列へのポインタ
format - 入力の読み取り方法を指定するヌル終端文字列へのポインタ
... - 受け取り引数

format 文字列は以下から構成されます。

  • 空白以外のマルチバイト文字 (ただし % を除く): 書式文字列中のそのような各文字は、入力ストリームからちょうど 1 つの同一の文字を消費するか、ストリームの次の文字が等しくない場合に関数を失敗させます。
  • 空白文字: 書式文字列内の任意の空白文字は、入力から利用可能な連続する空白文字をすべて消費します (あたかも std::isspace をループで呼び出すかのように決定)。書式文字列中では "\n", " ", "\t\t" または他の空白に違いはないことに注意してください。
  • 変換指定。各変換指定は以下の形式を持ちます。
  • 導入文字 %。
  • (オプション) 代入抑止文字 *。このオプションが存在する場合、関数は変換結果をどの受け取り引数にも代入しません。
  • (オプション) 最大フィールド幅を指定する整数 (0 より大きい) 最大フィールド幅。すなわち、現在の変換指定によって指定された変換を行う際に関数が消費を許される最大文字数です。幅が指定されていない場合、%s と %[ はバッファオーバーフローを引き起こす可能性があることに注意してください。
  • (オプション) 長さ修飾子。受け取り引数のサイズ、すなわち実際の変換先の型を指定します。これは変換の精度とオーバーフローの規則に影響を与えます。デフォルトの変換先の型は変換型ごとに異なります (以下の表を参照)。
  • 変換書式指定子。

以下の書式指定子が利用可能です。

変換
指定子
説明 期待される
引数の型
長さ修飾子→ hh h なし l ll j z t L
C++11 以降のみ利用可能→ はい はい はい はい はい
%
リテラル % と一致します。
N/A N/A N/A N/A N/A N/A N/A N/A N/A
c

文字 または 文字列 に一致します。

  • 幅指定子が使用された場合、正確に 幅 文字に一致します (引数は十分な領域を持つ配列へのポインタでなければなりません)。
  • %s や %[ とは異なり、配列にヌル文字を追加しません。
N/A N/A
char*
wchar_t*
N/A N/A N/A N/A N/A
s

非空白文字のシーケンス (文字列) に一致します。

  • 幅指定子が使用された場合、最大 幅 文字、または最初の空白文字までのいずれか先に現れた方まで一致します。
  • 一致した文字に加えて常にヌル文字を格納します (そのため引数配列には少なくとも 幅+1 文字分の余裕が必要です)。
[set ]

set で指定された文字の集合からの空でない文字シーケンスに一致します。

  • 集合の最初の文字が ^ の場合、集合に含まれないすべての文字が一致します。
  • 集合が ] または ^] で始まる場合、] 文字も集合に含まれます。
  • スキャンセット内の非最初の位置にある文字 - が範囲を示すかどうか ([0-9] のように) は処理系定義です。
  • 幅指定子が使用された場合、最大 幅 文字までのみ一致します。
  • 一致した文字に加えて常にヌル文字を格納します (そのため引数配列には少なくとも 幅+1 文字分の余裕が必要です)。
d

10 進整数 に一致します。

  • 数値の形式は、std::strtol が 10 を base 引数として期待するものと同じです。
signed char* または unsigned char*
signed short* または unsigned short*
signed int* または unsigned int*
signed long* または unsigned long*
signed long long* または unsigned long long*
std::intmax_t* または std::uintmax_t*
std::size_t*
std::ptrdiff_t*
N/A
b (C++26)

符号なし2 進整数 に一致します。

  • 数値の形式は、std::strtoul が 2 を base 引数として期待するものと同じです。
i

整数 に一致します。

  • 数値の形式は、std::strtol が 0 を base 引数として期待するものと同じです (基数は解析された最初の文字によって決定されます)。
u

符号なし10 進整数 に一致します。

  • 数値の形式は、std::strtoul が 10 を base 引数として期待するものと同じです。
o

符号なし8 進整数 に一致します。

  • 数値の形式は、std::strtoul が 8 を base 引数として期待するものと同じです。
x
X

符号なし16 進整数 に一致します。

  • 数値の形式は、std::strtoul が 16 を base 引数として期待するものと同じです。
n

これまでに読み取った文字数 を返します。

  • 入力は消費されません。代入カウントは増加しません。
  • 指定子に代入抑止演算子が定義されている場合、動作は未定義です。
a (C++11)
A (C++11)
e
E
f
F (C++11)
g
G

浮動小数点数 に一致します。

  • 数値の形式は、std::strtof が期待するものと同じです。
N/A N/A
float*
double*
N/A N/A N/A N/A
long double*
p

ポインタ を定義する処理系定義の文字シーケンスに一致します。

  • printf 関数群は %p 書式指定子を使用して同じシーケンスを生成する必要があります。
N/A N/A
void**
N/A N/A N/A N/A N/A N/A
ノート

n 以外のすべての変換指定子について、指定されたフィールド幅を超えず、かつ変換指定子が期待するものと正確に一致するか、またはそれが期待するシーケンスの接頭辞であるような、最長の入力文字シーケンスがストリームから消費されます。この消費されたシーケンスの後の最初の文字 (もしあれば) は読み取られずに残ります。消費されたシーケンスの長さがゼロであるか、または上記のように変換できない場合、ファイル終端、エンコーディングエラー、または読み取りエラーによってストリームからの入力が妨げられない限り、マッチング失敗が発生します。その場合は入力失敗です。

% 指定子を除き、入力アイテム (または %n の場合は入力文字数) は最初に変換指定子に適した型に変換されます。* で代入が抑制されなかった場合、変換結果はまだ書き込まれていない次の引数が指すオブジェクトに書き込まれます。このオブジェクトが適切な型を持っていない場合、または変換結果がオブジェクトで表現できない場合、動作は未定義です。

[, c, n 以外のすべての変換指定子は、入力の解析を試みる前に、先行するすべての空白文字 (あたかも std::isspace を呼び出すかのように決定) を消費して破棄します。これらの消費された文字は指定された最大フィールド幅にはカウントされません。

変換指定子 lc, ls, l[ は、あたかも最初の文字が変換される前にゼロに初期化された std::mbrtowc と std::mbstate_t オブジェクトを呼び出すかのように、マルチバイトからワイド文字への変換を実行します。

変換指定子 s と [ は、一致した文字に加えて常にヌル終端を格納します。宛先配列のサイズは指定されたフィールド幅より少なくとも 1 大きくなければなりません。宛先配列のサイズを指定せずに %s または %[ を使用することは、std::gets と同じくらい危険です。

固定幅整数型 (std::int8_t など) の正しい変換指定は、ヘッダ <cinttypes> で定義されています (ただし SCNdMAX, SCNuMAX などは %jd, %ju などと同義です)。

各変換指定子の動作の後にシーケンスポイント があります。これにより、同じ「シンク」変数に複数のフィールドを格納することができます。

指数部で数字が欠けた不完全な浮動小数点値を解析する場合、たとえば "100er" を変換指定子 %f で解析する場合、シーケンス "100e" (おそらく有効な浮動小数点数の最長の接頭辞) が消費され、"r" が残り、マッチングエラーが発生します (消費されたシーケンスは浮動小数点数に変換できません)。一部の既存の実装はこの規則に従わず、ロールバックして "100" のみを消費し、"er" を残します。例: glibc バグ 1765。

変換指定が無効な場合、動作は未定義です。

戻り値

正常に代入された受け取り引数の数 (最初の受け取り引数が代入される前にマッチング失敗が発生した場合はゼロになる可能性があります)、または最初の受け取り引数が代入される前に入力失敗が発生した場合は EOF。

計算量

保証されません。特に、一部の std::sscanf の実装は O(N) であり、N = std::strlen(buffer) [1] です。パフォーマンスの高い文字列解析については、std::from_chars を参照してください。

ノート

ほとんどの変換指定子が最初にすべての連続する空白を消費するため、次のようなコード

std::scanf("%d", &a);
std::scanf("%d", &b);

は、異なる行に入力された 2 つの整数を読み取ります (2 番目の %d は最初のものが残した改行を消費します)、または同じ行でスペースやタブで区切られたものを読み取ります (2 番目の %d はスペースやタブを消費します)。

%c などの先行空白を消費しない変換指定子は、書式文字列に空白文字を使用することで消費させるようにできます:

std::scanf("%d", &a);
std::scanf(" %c", &c); // ignore the endline after %d, then read a char

std::sscanf の一部の実装では std::strlen の呼び出しが含まれるため、実行時間が文字列全体の長さに線形になります。つまり、std::sscanf をループ内で呼び出して文字列の先頭から値を繰り返し解析する場合、コードが 2 次時間で実行される可能性があります (例)。

例

#include <clocale>
#include <cstdio>
#include <iostream>

int main()
{
    int i, j;
    float x, y;
    char str1[10], str2[4];
    wchar_t warr[2];
    std::setlocale(LC_ALL, "en_US.utf8");

    char input[] = "25 54.32E-1 Thompson 56789 0123 56ß水";
    // parse as follows:
    // %d: an integer 
    // %f: a floating-point value
    // %9s: a string of at most 9 non-whitespace characters
    // %2d: two-digit integer (digits 5 and 6)
    // %f: a floating-point value (digits 7, 8, 9)
    // %*d an integer which isn't stored anywhere
    // ' ': all consecutive whitespace
    // %3[0-9]: a string of at most 3 digits (digits 5 and 6)
    // %2lc: two wide characters, using multibyte to wide conversion
    const int ret = std::sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
                                &i, &x, str1, &j, &y, str2, warr);

    std::cout << "Converted " << ret << " fields:\n"
                 "i = " << i << "\n"
                 "x = " << x << "\n"
                 "str1 = " << str1 << "\n"
                 "j = " << j << "\n"
                 "y = " << y << "\n"
                 "str2 = " << str2 << std::hex << "\n"
                 "warr[0] = U+" << (int)warr[0] << "\n"
                 "warr[1] = U+" << (int)warr[1] << '\n';
}

出力:

Converted 7 fields:
i = 25
x = 5.432
str1 = Thompson
j = 56
y = 789
str2 = 56
warr[0] = U+df
warr[1] = U+6c34

関連項目

(C++11)(C++11)(C++11)
stdin、ファイルストリーム、またはバッファから書式付き入力の読み取り
変数引数リストを使用
(関数)
ファイルストリームから文字列を取得
(関数)
stdout、ファイルストリーム、またはバッファに書式付き出力を表示
(関数)
文字シーケンスを整数または浮動小数点値に変換
(関数)
scanf, fscanf, sscanf の C ドキュメント