では続いて、「数値」と同じように「文字列」をscanfで入力してみます。
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; scanf("%s", str); printf("%s\n", str); return 0; } |
<実行結果>
Hello ←scanfの入力 Hello 続行するには何かキーを押してください・・・
scanfで入力する時も「%s」を使えば入力出来ます。
ここでscanfの行を注意して見てください。
配列「str」の前に「&」が付いていません。
「&」を付けていても動作するのですが、「文字列」を表示する時には付けていないことが多いため、今後もサンプルでは付けないようにしておきます。
※このことについては、ずっと後に出てくる「ポインタ」という項目で説明します。
前回の説明の中で、最大文字数が10なので10文字くらい入りそうだと書きました。
作ったプログラムを実行する時に、誰もが正しく使ってくれるとは限りません。
10文字を超えて入力するとどうなるか試してみましょう。
<実行結果>
abcdefghijklmnopqrstuvwxyz ←scanfの入力 abcdefghijklmnopqrstuvwxyz
※ここまで表示された時点で↓のダイアログが表示される。
続行するには何かキーを押してください・・・
これは要するに「まともに動かなかった」ということです。
10文字程度しか容量の無い入れ物に26個もデータを入れることは出来ません。
用意した配列の枠を超えてデータが入力されるため、他のデータが入る領域を犯して破壊する可能性があります。
では、10文字ギリギリではどうでしょうか?
やってみてください。
<実行結果>
0123456789 ←scanfの入力 0123456789
※ここまで表示された時点で↓のダイアログが表示される。
続行するには何かキーを押してください・・・
10文字でもダメでしたね・・・
では、9文字ではどうでしょう?
<実行結果>
123456789 ←scanfの入力 123456789
続行するには何かキーを押してください・・・
問題なく動作します。
この状況を説明するために、配列の中身を覗いてみましょう。
まずは、宣言したばかりの配列の中身を見てみます。
基本的に初期値が入っていない変数や配列の中身は「不定」です。
どんなものが入っているのでしょうか。
for文を使って、配列の中身を1つずつ「文字」として表示してみます。
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; int i; for (i = 0; i < MAX_STRING; i++) { printf("%c\n", str[i]); } return 0; } |
<実行結果>
フ フ フ フ フ フ フ フ フ フ 続行するには何かキーを押してください・・・
私の実行環境では、カタカナの'フ'が10個表示されました。
※皆さんの環境では異なる結果になるかもしれません。
「10進数」で表示してみましょう。
<sample program 082-03>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; int i; for (i = 0; i < MAX_STRING; i++) { printf("%d\n", str[i]); } return 0; } |
<実行結果>
-52 -52 -52 -52 -52 -52 -52 -52 -52 -52 続行するには何かキーを押してください・・・
-52という「数値」が表示されました。
「文字コード表」に-52番なんてありましたでしょうか。
なぜこの数になっているか、分かりますか?
とりあえず考えてみてください。
ヒント「char型は8ビットの変数」
解答です。
char型は8ビットの変数です。
符号ありだと「-128から127」まで、符号なしだと「0から255」まで表現出来ます。
そして、文字コード表は符号なしの数で表示されています。
符号ありの-52は符号なしで表現するといくらになるでしょうか。
2の補数を使った2進数で-52を表現すると、
1100 1100
です。
「マイナスの表現」というコラムでの書き方だとこうなります。
1の位 が 0個 = 0
2の位 が 0個 = 0
4の位 が 1個 = 4
8の位 が 1個 = 8
16の位 が 0個 = 0
32の位 が 0個 = 0
64の位 が 1個 = 64
−128の位 が 1個 = −128
全部合計すると-52です。
一方同じビット列を符号なしで計算するとこうなります。
1の位 が 0個 = 0
2の位 が 0個 = 0
4の位 が 1個 = 4
8の位 が 1個 = 8
16の位 が 0個 = 0
32の位 が 0個 = 0
64の位 が 1個 = 64
128の位 が 1個 = 128
全部合計すると204です。
「文字コード表」の204番を見てください。
カタカナの'フ'ですね。
少し「文字列」から離れましたが、なぜそうなっているのかといった、仕組みを考えることは重要なことです。
今回はたまたまカタカナの'フ'が入っていましたが、初期値が入っていない配列の中身は不定です。
初期値を入れた状態も見てみましょう。
<sample program 082-02>のプログラムに、scanfで"ABC"と入力してみます。
<sample program 082-04>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; int i; scanf("%s", str); for (i = 0; i < MAX_STRING; i++) { printf("%c\n", str[i]); } return 0; } |
<実行結果>
ABC ←scanfの入力 A B C フ フ フ フ フ フ 続行するには何かキーを押してください・・・
"ABC"は表示されましたが、"ABC"の後ろに空白があります。
「数値」として見てみましょう。
上のプログラムの「%s」を「%d」に変えて、同じように"ABC"と入力してみます。
<sample program 082-02>のプログラムに、scanfで"ABC"と入力してみます。
<sample program 082-05>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING]; int i; scanf("%s", str); for (i = 0; i < MAX_STRING; i++) { printf("%d\n", str[i]); } return 0; } |
<実行結果>
ABC ←scanfの入力 65 66 67 0 -52 -52 -52 -52 -52 -52 続行するには何かキーを押してください・・・
'A'の文字コードは「10進数」で65です。
'B'は66、'C'は67ですね。
"ABC"の後ろには0がありました。
文字コードの0を確認してください。
「NUL」と書いてあります。
これは「ヌル」と読み、「NULL」と書くことも多いです。
色々な意味があるのですが、「文字」としての「ヌル」は「ヌル文字」と言って、文字列の最後を表す文字です。
「文字列」の初期値を入れたり、入力をした際には自動的に「ヌル文字」が文字列の最後に入ります。
そのため、10個分の配列を準備したとしても、「ヌル文字」分を考慮すると9文字しか入らないことになります。
初期値を設定した場合も見てみましょう。
<sample program 082-06>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING] = "ABC"; int i; for (i = 0; i < MAX_STRING; i++) { printf("%d\n", str[i]); } return 0; } |
<実行結果>
65 66 67 0 0 0 0 0 0 0 続行するには何かキーを押してください・・・
初期値を設定した場合は、配列の空いている部分に全てゼロが入ります。
初期値の文字数を10文字にしてみましょう。
<sample program 082-07>
#include <stdio.h> #define MAX_STRING 10 int main(void) { char str[MAX_STRING] = "ABCDEFGHIJ"; int i; for (i = 0; i < MAX_STRING; i++) { printf("%d\n", str[i]); } return 0; } |
コンパイルエラーで実行出来ません。
エラー内容を見てみましょう。
error C2117: 'str': 指定された配列には、初期化子が多すぎます。
最初の行にあるとおり、初期化子(初期化に使っているデータ)の数が多いのです。
10個の配列に10文字入れようとしていますが、「ヌル文字」分が考慮されておらず、入りきらないのでエラーとなっています。
C言語で「文字列」を扱う際には、「ヌル文字」の存在を常に頭に置いてください。
「ヌル文字」を利用するプログラムも後々やっていきます。
ここで、コラムを3つ紹介しますので、順に読んでください。
3.文字列入力関数