scanf
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/11/23 00:15 UTC 版)
ナビゲーションに移動 検索に移動標準入力(大抵はキーボード)からの入力を、書式に従って変数に読み込む機能を持つ。標準出力関数のprintfと対比させて考えると分かりやすい。
ユーザーからの入力を受ける、ごく基本的な機能を持つにもかかわらず、後述するように異常入力(エラー)に配慮すると相応の手間がかかるため、テストプログラムや入門書を除いてはあまり使われない。
このファミリーの関数には、入力ストリームを指定できる fscanf や、メモリ上の文字列ストリームを入力対象とする sscanf などがある。
形式
stdio.h内で以下の様に宣言されている。
int scanf(const char *format, ...);
printf と同様、第1引数のformat
は、それに続く可変長の実引数の変換方法(書式)を指定する。また戻り値は入力(スキャン)に成功した入力項目の数が返される。
利用例を以下に示す。
#include <stdio.h>
int main(void)
{
int x; /* スキャン結果を格納する変数。 */
printf("x = ? "); /* 入力を促すプロンプト。 */
/* スキャンと結果の確認。 */
if (scanf("%d", &x) == 1) {
printf("スキャン結果 = %d\n", x);
}
else {
printf("スキャン失敗\n");
}
return 0;
}
変換指定
scanf の変換指定は次の形式をとる。
% [代入抑止][最大フィールド幅][長さ修飾子]変換指定子
代入抑止
フラグ | 意味 |
---|---|
* | フォーマットに合わせて入力を読み込むが実引数に代入はされない。 |
例えば
char c;
scanf("%*c%c", &c);
というコードがあり、 "ab"という入力があった場合 1文字目の 'a' は無視され 2文字目の 'b' という文字が代入される。
長さ修飾子
修飾子 | 意味 | 導入バージョン |
---|---|---|
hh | 実引数は char 型 | C99以降 |
h | 実引数は short 型 | 全バージョン |
l(エル) | 実引数は long 型または wchar_t 型または double 型 | wchar_t についてはC95以降 |
ll(エルエル) | 実引数は long long 型 | C99以降 |
j | 実引数は intmax_t 型 | C99以降 |
z | 実引数は size_t 型 | C99以降 |
t | 実引数は ptrdiff_t 型 | C99以降 |
L | 実引数は long double 型 | 全バージョン |
変換指定子
指定子 | 意味 | 導入バージョン |
---|---|---|
d,i | 10進符号付き整数 | 全バージョン |
u | 10進符号無し整数 | 全バージョン |
o | 8進符号無し整数 | 全バージョン |
x,X | 16進符号無し整数 | 全バージョン |
e,E | 浮動小数点数 | 全バージョン |
f,F | 浮動小数点数 | 全バージョン |
g,G | 浮動小数点数 | 全バージョン |
a,A | 浮動小数点数 | C99以降 |
c | 文字 | 全バージョン |
s | 文字列 | 全バージョン |
p | ポインタの値、対応する引数は void* になる。 | 全バージョン |
n | 整数変数に出力済み文字数を格納 | 全バージョン |
% | '%'の入力 | 全バージョン |
[...] | [ ]内で囲まれた文字だけを取得し、 それ以外の文字が現れた場所以降は入力を終了する(下記参照)。 |
全バージョン |
[ ] は例えば
char str[256];
scanf("%[abc]", str);
というコードがあり、入力に "babaacdeabfghijabcef" という文字列が入った場合、str には "babaac" という文字列のみが入力され、残りの文字列は入力されずに終了する。strに代入されなかった、"deabfghijabcef"は入力ストリームに残る形となる。また[^ ... ]とした場合は逆に[ ]内の文字が入ってくるまで文字を読み込む。 例えば、
char str[256];
scanf("%[^abc]", str);
という場合、"ghetbceajk"と入力すると、str には"ghet"が代入される。上記と同様に、入力されなかった文字列は入力ストリームに保持される。
コード例
ソース:
#include <stdio.h>
#include <limits.h>
int main(void)
{
int n1, n2, nadd, nsub, nmul, ndiv, nmod;
printf("1つ目の入力数値:");
if (scanf("%d", &n1) != 1) {
puts("スキャン失敗");
return -1;
}
printf("2つ目の入力数値:");
if (scanf("%d", &n2) != 1) {
puts("スキャン失敗");
return -1;
}
if (n2 == 0) {
/* ゼロ除算防止のチェック。 */
puts("2つ目の数値は非ゼロを入力してください");
return -1;
}
if (n1 == INT_MIN && n2 == -1) {
/* 除算と剰余のオーバーフローエラー防止のチェック。 */
puts("オーバーフローしない数値の組み合わせを入力してください");
return -1;
}
nadd = n1 + n2;
nsub = n1 - n2;
nmul = n1 * n2;
ndiv = n1 / n2;
nmod = n1 % n2;
printf("%d + %d = %d\n", n1, n2, nadd);
printf("%d - %d = %d\n", n1, n2, nsub);
printf("%d * %d = %d\n", n1, n2, nmul);
printf("%d / %d = %d + %d / %d\n", n1, n2, ndiv, nmod, n2);
return 0;
}
出力結果の例:
1つ目の入力数値:60
2つ目の入力数値:21
60 + 21 = 81
60 - 21 = 39
60 * 21 = 1260
60 / 21 = 2 + 18 / 21
- ^ “[迷信] scanf ではバッファオーバーランを防げない” (日本語). C/C++迷信集. 株式会社きじねこ. 2010年2月28日閲覧。 “書式指定が不適切なために発生する脆弱性であって、scanf の問題ではありません。”
固有名詞の分類
- scanfのページへのリンク