「文字列」の入力用にscanfを使ってきましたが、scanfには色々と知っておかなければならない点があります。
<sample program 082-01>に↓の文字列を打ち込んでみてください。
入力文字列 ABC DEF ※ABCとDEFの間に半角空白を入れてください。
<実行結果>
ABC DEF ←scanfの入力 ABC 続行するには何かキーを押してください・・・
scanfは「%s」を指定した場合、半角空白を「区切り文字」として認識し、"DEF"を入力バッファという場所に残してしまいます。
"DEF"は残っていますから、再びscanfを実行すると読み込むことが出来ます。
<sample program col027-01>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%s", str); printf("%s\n", str); scanf("%s", str); printf("%s\n", str); return 0; } |
<実行結果>
ABC DEF ←1回目のscanfの入力 ABC DEF 続行するには何かキーを押してください・・・
1回しか入力していないのですが、scanfは2回実行されました。
1回目のscanfで"ABC"を読み込み、2回目のscanfで"DEF"を読み込んでいます。
これを解消するためには、新しい書式が必要になります。
<sample program col027-02>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%[^\n]", str); printf("%s\n", str); return 0; } |
<実行結果>
ABC DEF ←scanfの入力 ABC DEF 続行するには何かキーを押してください・・・
まず、"%[]"は、[]内に書かれた文字が続く間、バッファから文字を取り出すという意味になります。
次のようにプログラムを書くと実際に見ることが出来ます。
<sample program col027-03>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%[abcdef]", str); printf("%s\n", str); return 0; } |
<実行結果>
abc ←scanfの入力 abc 続行するには何かキーを押してください・・・
<実行結果>
aakk ←scanfの入力 aa 続行するには何かキーを押してください・・・
<実行結果>
aakkaa ←scanfの入力 aa 続行するには何かキーを押してください・・・
[]内に書かれている"abcdef"のいずれかの文字が入力されている間は配列strに文字を読み込んでいます。
しかし、それ以外の文字が出てくると、文字を読み込むのをやめています。
読み込まれなかった文字はバッファに残り、次の入力で読み込まれます。
では、"%[^\n]"はどういう意味かと言うと、
「^(カレット)」は「否定(〜以外)」という意味で使われており、「改行以外の文字」という意味になります。
ですから、「改行以外の文字が続いている間は読み込まれる」という意味です。
こうすれば、半角空白も読み込んでくれますが、入門書などには書かれていないことが多いです。
もう一つ、知っておいて欲しいことを書きます。
下のプログラムで10文字以上の文字を入力するとどうなるか、以前試しましたよね。
<sample program col027-04>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%s", str); printf("%s\n", str); return 0; } |
<実行結果>
abcdefghijklmn ←scanfの入力 abcdefghijklmn
※ここまで表示された時点で↓のダイアログが表示される。
続行するには何かキーを押してください・・・
9文字までしか入力できない!と分かっていてもミスなどが起きる可能性もあります。
誰がどのように使うか分からないため、対策を書きます。
<sample program col027-05>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%9s", str); printf("%s\n", str); return 0; } |
<実行結果>
abcdefghijklmn ←scanfの入力 abcdefghi 続行するには何かキーを押してください・・・
入力は15文字分ですが、配列strには9文字しか入っていません。
入力の書式を"%s"から"%9s"に変更したため、9文字までしか読み込まなくなりました。
これなら大丈夫そうですね。
しかしこれでは半角空白の問題が再浮上してきます・・・
両方を合わせると↓のような書式になります。
<sample program col027-06>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%9[^\n]", str); printf("%s\n", str); return 0; } |
<実行結果>
abc def ghi jkl ←scanfの入力 abc def g 続行するには何かキーを押してください・・・
ちゃんと両方に対応出来ていることを確認してください。
入力できる文字数を制限しましたが、問題が残っています。
制限されて残った文字は入力バッファに残り、再びscanfを実行すると読み込める、と先頭で書きました。
今回も同じように確かめてみましょう。
<sample program col027-07>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%9[^\n]", str); printf("%s\n", str); scanf("%9[^\n]", str); printf("%s\n", str); return 0; } |
<実行結果>
abc def ghi ←scanfの入力 abc def g hi 続行するには何かキーを押してください・・・
9文字しか入りませんので、"hi"という文字列はバッファに残っていました。
もう一度scanfを実行することで、バッファにあった"hi"を読み込んで表示されました。
しかし、毎回バッファに文字が残っているかどうかは分かりません。
9文字以内できちんと入力される時もあれば、オーバーして残る場合もあります。
そこで、次の書式です。
<sample program col027-08>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%9[^\n]%*[^\n]", str); printf("%s\n", str); scanf("%9[^\n]%*[^\n]", str); printf("%s\n", str); return 0; } |
<実行結果>
abc def ghi ←scanfの入力 abc def g abc def g 続行するには何かキーを押してください・・・
"%[^\n]"の後ろに"%*[^\n]"を追加しました。
"%*"は後ろに続く書式に合わせてデータをバッファから取り出しますが、配列には入れません。
今回の書式は"[^\n]"改行以外、ですから改行以外の文字を取り除きました。
でも、おかしいです。 みなさんも実際に実行していれば気づくと思います。
↑のプログラムが、きちんと動作するのであれば、2回目のscanfの前に入力バッファはクリアされ、2回目のscanfで別も文字列を入力出来るはずです。
原因は3行上にありますが、「改行」が残っているからです。
2回目のscanfは、残った「改行」だけを読み込んで終わっているのです。
この「改行」を消すため、↓のように書式を追加します。
<sample program col027-09>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%9[^\n]%*[^\n]%*c", str); printf("%s\n", str); scanf("%9[^\n]%*[^\n]%*c", str); printf("%s\n", str); return 0; } |
<実行結果>
abc def ghi ←1回目のscanfの入力 abc def g jkl mno pqr ←2回目のscanfの入力 jkl mno p 続行するには何かキーを押してください・・・
一番後ろに"%*c"を付けて、改行文字を取り除きました。
きちんと2回目の文字列も入力出来ています。
ということは、1回目の入力ではみ出した部分は2回目の入力時には無くなっているということです。
ブラウザの戻るボタンで戻ってください。