scanf による文字列の入力
CoddyのCジャーニー「Logic & Flow」セクションの一部 — レッスン 14/63。
ヌル終端文字による文字列の仕組みを理解したところで、ユーザーから文字列の入力を取得する方法を学ぶ時が来ました。scanf関数は%s書式指定子を使用して文字列を読み取ることができますが、理解しておくべき重要な制限事項があります。
scanfで文字列を読み取るには、%sフォーマットを使用し、文字配列の名前を渡します(配列名はすでにアドレスであるため、&演算子は不要です):
char word[50];
printf("Enter a word: ");
scanf("%s", word);
printf("You entered: %s\n", word);しかし、scanf("%s", ...) には重大な制限があります。それは、空白文字(スペース、タブ、または改行)に遭遇するとすぐに読み取りを停止することです。これは、ユーザーが "Hello World" と入力した場合、scanf は "Hello" だけを取り込み、"World" を入力バッファに残してしまうことを意味します。
もう一つの深刻な懸念は、scanf が入力が配列に収まるかどうかをチェックしないことです。配列が保持できる長さよりも長い単語が入力されると、バッファオーバーフローが発生し、プログラムがクラッシュしたり、セキュリティ上の脆弱性が生じたりする可能性があります。常に、文字配列が想定される入力に対して十分な大きさであることを確認してください。
これらの制限があるにもかかわらず、scanf("%s", ...) は単一の単語を読み取るのには非常に適しています。これは、次のチャレンジでまさに練習する内容です。
チャレンジ
簡単scanf を使用してユーザーから文字列入力を読み取り、それを表示する C プログラムを作成してください。プログラムは以下の手順に従う必要があります:
- ユーザーの入力を格納するために、30個の要素を持つ
usernameという名前の文字配列を宣言します。 - 別の入力を格納するために、25個の要素を持つ
hobbyという名前の文字配列を宣言します。 printfを使用して、ユーザーに "Enter your username:" というメッセージを表示します。%sフォーマット指定子を伴うscanfを使用して、username配列にユーザー名を読み取ります。printfを使用して、ユーザーに "Enter your hobby:" というメッセージを表示します。%sフォーマット指定子を伴うscanfを使用して、hobby配列に趣味を読み取ります。printfを使用して、以下に示す正確な形式で両方の文字列を出力します。
入力は、2つの独立した単語(各単語内にスペースは含まれません)として提供されます。
出力は、以下の形式で結果を表示する必要があります:
Enter your username:
Enter your hobby:
Hello [username], your hobby is [hobby]!例えば、ユーザーがユーザー名として "Alice"、趣味として "reading" と入力した場合、出力は以下のようになります:
Enter your username:
Enter your hobby:
Hello Alice, your hobby is reading!このチャレンジでは、%s フォーマット指定子を用いた scanf による文字列入力の読み取り、十分なサイズでの適切な文字配列の宣言、および printf を使用したユーザー入力とフォーマット済み出力の組み合わせについての理解をテストします。
チートシート
ユーザーから文字列の入力を読み取るには、scanf を %s フォーマット指定子と一緒に使用します。
char word[50];
printf("Enter a word: ");
scanf("%s", word);
printf("You entered: %s\n", word);scanf("%s", ...) の重要な制限事項:
- 空白文字(スペース、タブ、改行)で読み取りが停止します
- 単一の単語のみをキャプチャします - "Hello World" は "Hello" だけになります
- バッファオーバーフローの保護がありません - 配列が十分に大きいことを確認してください
- 配列名に
&演算子を使用しないでください(配列名はすでにアドレスです)
自分で試してみよう
#include <stdio.h>
int main() {
// TODO: ここで文字配列を宣言してください
// TODO: 入力を促して読み取るコードをここに記述してください
// TODO: 最終的な出力メッセージを表示してください
return 0;
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。