C言語 プログラミング

 

スポンサードリンク

 

scanf関数とは

scanf関数は、標準入力からから入力された値を書式文字列に従って読み取って変数に格納する関数です。

読み方printf同様にscanf(スキャンエフ)、末尾のfはformatを意味します。

次のサンプルコードでは、int型の変数monthに、今月の月を記憶し2、回目のprintf関数でmonthを読み込んで表示しています。

 

scanf – 書式設定

int scanf(const char *format, …)

%[代入抑止文字][最大フィールド幅][変換修飾子]変換指定子

 

代入抑止文字 / *

代入抑止文字(*) 意味
* フィールドのスキャンのみ行われ、アドレス引数に代入はされません。

次のサンプルコードでは、scanf関数で変数numに1000を入力するもアスタリスクを使っているので実際には代入されません。

 

最大フィールド幅 / Width

最大フィールド幅(width) 意味
0以外の10進整数 最大フィールド幅を設定します。

次のサンプルコードでは、4桁までの整数をint型変数dayに記憶して日付を表示します。

最大フィールド幅を4に設定しているため、4桁以上の数字は変数に記憶されません。

長さ修飾子 / Modifiers

長さ修飾子(modifiers) 意味
hh 実引数がchar型であることを指定する。
h 実引数がshot型であることを指定する。
l 実引数がlong型であることを指定する。
ll 実引数がlong long型であることを指定する。
j 実引数はintmax_t型であることを指定する。
z 実引数はsize_t型であることを指定する。
t 実引数はptrdiff_t型であることを指定する。
L 実引数がlong double型であることを指定する。

 

変換指定子 / Type

変換指定子(type) 意味 引数の型
d 10進整数 int *
i 整数 int *
o 8進整数 int *
u 10進整数 unsigned int *
x, X 16進整数 int *
e, E, f, g, G 浮動小数点数 float *
c フィールド幅で指定された長さの文字の並び char *
s 非空白類文字の並びの集合 char *
p 処理系定義の文字の並びの集合 void *
n 入力を読みとらない。入力ストリームから読み取った文字数を格納する。 int *
% 一つの%を照合 %
変換指定子(type) 意味 引数の型
lf double型の浮動小数点数 double *
ld long型の整数 long *

scanf関数の注意点

scanf関数を使う上でいくつかの注意点が存在します。

改行文字

入力文字が数字の場合は問題ありませんが、入力が文字(char)の場合は改行文字に注意する必要があります。

上のサンプルコードでは変数bの入力がスキップされ、出力時には空白が表示されています。

これは変数aへの入力を確定する際のエンターキーによって、改行文字”\n”がストリーム上に残されてしまうためにおきる現象です。

変数aには”a”が記憶され、変数bにはストリーム上に残った改行コード”\n”が記憶されます。

変数bへの入力は”\n”で自動的に行われてしまったため、ユーザーが変数bに入力する機会は無くなり、変数cの入力が開始されます。

これらはprintf関数で表示した結果からも見て取れます。

変数bには改行文字が記憶されていたため”b = “のあとに改行が行われています。

 

これらを防ぐ方法としては、scanf関数の%の前に空白を入れることで回避できます。

%の前に空白を含めることで入力前の空白(改行コードを含む)を読み飛ばすことを意味しています。

ただしこの方法では半角スペースを代入する際にまた困ったことになります。

その場合は”%*c”を用いることで対処できます。

空白 / タブ

scanf関数は空白とタブを改行文字と同じ区切り文字として扱います。

下記は半角文字を含む文字列”Hello world”を入力した際の結果とサンプルコードです。

先述の通り半角文字は区切り文字として理解されるため半角文字以降の”world”が代入されません。

またそればかりでなく”world”はストリーム上に残されることになり、続くscanf関数がある場合には自動的に”world”が代入されます。

 

この問題の対策としては、変換指定子[]を用いて次の様に記述します。

このコードでは改行文字以外の全ての文字列を全て変数aに代入します(空白、タブも含まれる)

 

尚、先述した入力時の改行コードを考慮した場合には次のように記述する。

バッファオーバーフロー

scanf関数は他のC言語の文字列関数と同様に、バッファオーバーフローの危険性があります。

上記のコードでは変数aに入力できる文字列は、終端文字(’\0’)を除く19バイトまでしか入力することができない。

それ以上の文字列が入力された場合バッファオーバーフローが発生する。

コマンドプロンプトでバッファオーバーフローにより強制終了した例のスクリーンショットです。
コマンドプロンプトで上記のサンプルコードに19バイト以上の文字列を入力したところ問題が発生し停止した。

kの問題を防ぐためのコードは次のとおりである。

C言語 – scanf関数 キーボードから値を読み取る
Tagged on:

コメントを残す