C言語のscanfを勉強して、文字の読み取りをしたいな。エラーが出たけど何がダメなの?
こちらの悩みを解決しますね。
本記事の内容
・scanfとは?
・【scanfの謎】文字列だとカンマの後に「&」を付けない理由
・C言語でscanfエラーが出たときの対処法
この記事を書いている自分は、一日中プログラミングしていた過去がありました。現在、そこで学んだC言語について解説中です。
今回は、1からscanfの使い方を解説し、その後エラーが出たときの対処法を紹介します。
scanfはエラーが出やすいですが、この方法を使えばエラーは出ません。
scanfとは?
scanfとは、プログラム実行後に、変数に数字や文字を代入するための関数です。scanfを使って代入することを入力と言います。
また、scanfでは文字列の入力もできますが、配列も同時に使う必要ありですね。
詳しくは下の記事をどうぞ。
»C言語 入門 配列に文字列を代入!(¥0の解説もします!)
ところで、プログラム実行後に代入できることのメリットは何だと思いますか?
多分、以下のようなメリットがありますよね。
✔プログラム実行後に代入できることのメリット
- 簡単に代入できる
- 本格的なツールがつくれる
この2つをまとめると、
誰でも簡単に変数に代入して、出力結果を得ることができるということですね。
僕たちが普段、スマホで文字を入力したり、電卓に数字を打ち込んで計算できたりするのは、scanfのような入力関数があるからなんです。
(全部がC言語のscanfを使ってるわけでは無いです。他のプログラミング言語を使っている可能性もあります。)
普段からプログラムをいじらずに、既に完成したツールを使えるのは、このためです。
このことを理解した上で、scanfの勉強に取り組むとそのありがたみが分かるかと思います。
こちらの記事では、数字と文字を代入するだけのプログラム、scanfで文字を代入して、ASCIIコードに変換するプログラムを説明しました。
今回は数字を入力するプログラム、文字列を入力するプログラムの説明をします。
scanfで数字を入力するプログラム
数字を入力するプログラムは文字を入力するプログラムの変換書式とデータ型を変えるだけでできます。
具体的に言うとデータ型「char」を「int」に、変換書式「%c」を「%d」に変えるだけです。
よくわからないという方は、先ほど紹介した記事をご覧ください。
scanfで数字を入力して、5倍するプログラムは次のようになります。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int suuji;
scanf("%d", &suuji);
suuji *= 5;
printf("%d", suuji);
}
scanfで文字列を入力して出力するプログラム
文字列を入出力するには以下の3つが必要です。
✔文字列の入出力に必要なもの
- 配列
- char
- %s
過去の記事にて、配列の説明をしているので参考にしてみてください。
「%s」は文字列を入出力するためだけにある変換書式です。重要なので必ず覚えましょう。
下はscanfで文字列を入力し、printfで出力するときのプログラムです。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char moji[1000];
scanf("%s", moji);
printf("%s", moji);
}
このプログラムで分かりにくいところを解説していきます。
この5つについて解説していきます。
【scanfの謎】文字列だと&を付けない理由(アドレスを使うため)
文字列の場合だけカンマの後に「&」を付けません。
scanf("%s", moji);
printf("%s", moji);
見落としがちなので、もう一度見てください。scanfとprintfどちらも&が付いていません。
実は、scanfでカンマの後に入力しているのは変数ではなくアドレスなのです。
配列だと、アドレスは&と [ ] を付けないで表すため、このようなプログラムになっています。
これが分からない人は下の記事でポインタとアドレスの関係を復習しましょう。
よく、文字列にも「&」を付けたまま、「エラーが出てしまいました。」という相談を受けます。
この辺は「あるある」ですし重要なので、もう一度復習しましょう。
変数、ポインタ、配列によって「代入された数値」、「アドレス」の表し方は異なります。
軽くまとめるとこんな感じです。
変数「int a;」での代入された数値、アドレスの表し方
変数での値の表し方 | a(そのまま) |
変数でのアドレスの表し方 | &a(&付ける) |
ポインタ「int *pa」での代入された数値、アドレスの表し方
ポインタでの値の表し方 | *pa(そのまま) |
ポインタでのアドレスの表し方 | pa(*取る) |
配列「int a[配列数+1]」での代入された数値、アドレスの表し方
配列での値の表し方 | a[ ](数字取る) |
配列でのアドレスの表し方 | a([ ]も取る) |
C言語でscanfエラーが出たときの対処法
scanfを使ってエラーが出てくる原因は、SDLチェックです。
SDLとはSecurity Development Lifecycleの略で、使い方によってはセキュリティ上の問題を起こすような旧式の関数の使用にエラーを出します。
scanf以外にもgetsやstrcpyなどでも同じ現象が起こります。
✔scanfでエラーが出たときの対処法
- 「#define _CRT_SECURE_NO_WARNINGS」を使う
- SDL チェックを無効にする
- scanf以外の関数を使う
上から順に解説していきますね。
「#define _CRT_SECURE_NO_WARNINGS」を使う
「#define _CRT_SECURE_NO_WARNINGS」とは、SDLチェックを回避するための呪文だと思ってください。
scanf使うときに、プログラムの1番初めに書くことで、SDLチェックを回避できます。
SDLチェックを無効にする
SDLチェックを無効にすることもできます。
プロジェクトを作成するときに、
[プロパティ] → [構成プロパティ] → [C/C++] → SDL チェックを無効
を選択すれば無効にできます。
以上の3つを試してもエラーが出ていたら、SDLチェック以外に原因があります。
たとえば他にも使っているデータ型や変換書式が原因だったりします。
このサイトの最初の方を読めば「scanf」の正しい使い方が分かるので読み直しましょう。
scanf以外の関数を使う
scanfを使わなくても、getchar、getsなどを使えば文字の入力ができます。
それぞれの関数に微妙な違いがあるので、特徴を知ることが重要です。
また、scanfの代わりにscanf_sという関数もあったりします。
この話をもうちょっと詳しく解説します。
scanf_sとは?
scanf_sとは、scanf関数から派生した関数で、よりセキュリティ強化されているためSDLチェックによるエラーが出ない関数です。
最初に紹介した「5倍するプログラム」をscanf_sを使って書き換えてみます。
#include<stdio.h>
int main()
{
int suuji;
scanf_s("%d", &suuji);
suuji *= 5;
printf("%d", suuji);
}
まとめ:scanfの使い方とは?(エラーの対処法も)
scanfでプログラム実行後に代入することのメリットは以下の2つですね。
✔プログラム実行後に代入できることのメリット
- 簡単に代入できる
- 本格的なツールがつくれる
また、文字列の代入には以下の3つが必須です!
✔文字列の入出力に必要なもの
- 配列
- char
- %s
そして、SDLチェックを回避する方法は全部で3つですね。
全部覚える必要は無いです。
個人的には「#define _CRT_SECURE_NO_WARNINGS」が使いやすいと思うので、今後このサイトではそれを使います。
今回は以上です!
次は、乱数の発生方法を勉強しましょう。
ではでは~👋
コメント