scanf はscan formatted の略で、標準入力からテキストを読み取って解析するC 標準ライブラリ 関数です。
この関数は、入力テキストのレイアウトを指定する書式文字列パラメータを受け入れます。この関数は、入力テキストを解析し、データ型に基づいて値を変数にロードします。
同様の関数は、 ALGOL 68など、C より前readfに別の名前で存在していました。
入力フォーマット文字列は、フォーマットされた出力 (テンプレート) を提供する出力フォーマット文字列 ( printf を参照) を補完します。
歴史
マイク・レスクのポータブル入出力ライブラリ(を含む)は、バージョン7scanfで正式にUnixの一部となった。[1]
使用法
この関数は、標準入力からscanf数値やその他のデータ型の入力を読み取ります。
次の C コードは、標準入力から可変数のフォーマットされていない 10 進整数を読み取り、それぞれを別々の行に出力します。
#include <stdio.h>
int main ( void )
{
整数n ;
( scanf ( "%d" 、& n ) == 1 )の間
printf ( "%d \n " , n );
0 を返します。
}
入力の場合:
456 123 789 456 12
456 1
2378
出力は次のようになります。
456
123
789
456
12
456
1
2378
単語を印刷するには:
#include <stdio.h>
int main ( void )
{
文字単語[ 20 ];
if ( scanf ( "%19s" 、単語) == 1 )
puts (単語);
0 を返します。
}
プログラマーがプログラムに読み取らせたいデータ型が何であっても、引数 (上記など&n)はメモリを指すポインターでなければなりません。そうでない場合、関数は、入力を取得しようとしている変数のメモリ位置を指すのではなく、メモリの間違ったセクションを上書きしようとするため、正しく実行されません。
最後の例では、引数にアドレス演算子 ( &) は使用されていません。は の配列wordの名前であるため、(アドレスに評価されるすべてのコンテキストで) 配列の最初の要素へのポインターと同等です。式は数値的には同じ値に評価されますが、意味的にはまったく異なる意味を持ち、配列の要素ではなく配列全体のアドレスを表します。出力を文字列に割り当てるときは、この事実に留意する必要があります。
char&wordscanf
は標準入力からのみ読み取るように指定されているため、 PHPなどのインターフェースscanfを持つ多くのプログラミング言語には、やなどの派生語がありますが、 自体にはありません。
sscanffscanfscanf
書式文字列の仕様
の書式プレースホルダはscanf、その逆関数であるのものとほぼ同じですprintf。printfと同様に、POSIX拡張n$が定義されています。[2]
書式文字列には、定数(つまり、書式設定プレースホルダーでscanfはない文字)はほとんどありません。これは主に、プログラムが既知のデータを読み取るように設計されていないためです。ただし、明示的に指定された場合は、これらを受け入れます。例外は、1つ以上の空白文字で、入力内のすべての空白文字が破棄されます。[2]
最もよく使用されるプレースホルダーの一部を次に示します。
%a: 浮動小数点数を 16 進表記でスキャンします。%d: 整数を符号付き10 進数としてスキャンします。%i: 整数を符号付き数値としてスキャンします。 に似ていますが、 が前に付いた場合は%d数値を16 進数0xとして解釈し、が前に付いた場合は8 進数0として解釈します。たとえば、 を使用すると文字列は03131 と読み取られ%d、 を使用すると 25 と読み取られます。の%iフラグは、 への変換とへの変換を示します。h%hishorthhchar%u: 小数をスキャンしますunsigned int(C99 標準では、入力値のマイナス記号はオプションであるため、マイナス記号が読み取られてもエラーは発生せず、結果は負の数の2 の補数(非常に大きな値になる可能性が高い) になります。 を参照してくださいstrtoul()。[検証に失敗しました] ) 同様に、%huは をunsigned short、 は%hhuをスキャンしますunsigned char。%f:浮動小数点数を通常の(固定小数点)表記でスキャンします。%g,%G: 通常表記または指数表記のいずれかで浮動小数点数をスキャンします。%g小文字を使用し、%G大文字を使用します。%x,%X: 整数を符号なし16 進数としてスキャンします。%o: 整数を8進数としてスキャンします。%s:文字列をスキャンします。スキャンは空白で終了します。文字列の末尾にはヌル文字が格納されます。つまり、指定されたバッファは指定された入力長より少なくとも 1 文字長くなければなりません。%c: 文字 (char) をスキャンします。ヌル文字は追加されません。- 空白文字: 空白文字があると、0 個以上の空白文字のスキャンがトリガーされます。空白文字の数と種類は、どちらの方向でも一致する必要はありません。
%lf:倍精度浮動小数点数としてスキャンします。"long" 指定子を使用した "float" 形式。%Lf: long double浮動小数点数としてスキャンします。「float」は「long long」指定子をフォーマットします。%n: 何も期待されません。入力からこれまでに消費された文字数は、次のポインターを通じて格納されます。このポインターは、int へのポインターである必要があります。これは変換ではなく、関数によって返されるカウントは増加しません。
上記は、数値修飾子と、パーセント記号と文字の間にある「long」および「long long」を表すl,修飾子と組み合わせて使用できます。パーセント記号と文字の間に数値を置くこともできます。修飾子がある場合は、その前にスキャンする文字数を指定します。パーセント記号の直後のオプションのアスタリスク( ) は、この書式指定子によって読み取られたデータが変数に格納されないことを示します。このドロップされた変数には、書式文字列の後ろに引数を含めないでください。
Llong*
printfの修飾子ffはscanfには存在しないため、入力モードと出力モードに違いが生じます。修飾子llとhh修飾子はC90標準には存在しませんが、C99標準には存在します。[3]
フォーマット文字列の例は次の通りです。
"%7d%s %c%lf"
上記の書式文字列は、最初の 7 文字を 10 進整数としてスキャンし、スペース、改行、またはタブが見つかるまで残りを文字列として読み取り、最初の非空白文字が見つかるまで空白を消費し、その文字を消費し、最後に残りの文字をdoubleとしてスキャンします。したがって、堅牢なプログラムscanfでは、呼び出しが成功したかどうかを確認し、適切なアクションを実行する必要があります。入力が正しい形式でなかった場合、誤ったデータは入力ストリームに残っているため、新しい入力を読み取る前に破棄する必要があります。これを回避する別の方法は、 を使用してから読み込んだ文字列を調べることです。最後のステップは、たとえば、
fgetsによって実行できます。sscanf
多くの float 型文字a、e、f、gの場合、多くの実装ではそのほとんどを同じパーサーにまとめることを選択します。Microsoft MSVCRT はe、f、gでこれを行います[4]が、glibc は4 つすべてでこれを行います[2] 。
ISO C99には、inttypes.hプラットフォームに依存しないコーディングで使用するためのいくつかのマクロを含むヘッダーファイルが含まれていますscanf。これらは二重引用符の外側に記述する必要があります。例:scanf("%" SCNd64 "\n", &t);
マクロの例は次のとおりです。
脆弱性
scanfは、書式指定文字列攻撃に対して脆弱です。書式指定文字列に文字列と配列のサイズの制限が含まれていることを確認するために、細心の注意を払う必要があります。ほとんどの場合、ユーザーからの入力文字列のサイズは任意であり、関数scanfが実行される前に決定することはできません。つまり、%s長さ指定子のないプレースホルダーは本質的に安全ではなく、バッファオーバーフローに悪用される可能性があります。もう1つの潜在的な問題は、構成ファイルやその他のユーザー制御ファイルに格納されている書式指定文字列など、動的な書式指定文字列を許可することです。この場合、書式指定文字列を事前にチェックして制限を適用しない限り、許可される入力文字列の長さを指定することはできません。これに関連して、実際のvarargリストと一致しない、追加のまたは不一致の書式指定プレースホルダーがあります。これらのプレースホルダーは、 varargsの特定の実装に応じて、スタックから部分的に抽出されたり、望ましくない、または安全でないポインターを含む場合があります。
参照
参考文献
- ^ McIlroy, MD (1987). A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (技術レポート). CSTR. Bell Labs. 139.
- ^ abc – Linuxプログラマーズマニュアル– ライブラリ関数
- ^ C99 標準、§7.19.6.2「fscanf 関数」alinea 11。
- ^ 「scanf 型フィールド文字」。docs.microsoft.com。2022年 10 月 26 日。
外部リンク
- – システム インターフェース リファレンス、The Single UNIX 仕様、バージョン 4、The Open Group
- std::scanf の C++ リファレンス
