質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

3085閲覧

C言語で複数人の名前を入力させたい

Cpro

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2019/06/28 12:02

編集2019/06/28 12:23

C言語で名前を読み取らせて最後に表示させるプログラムを作っています。

Tadao
Tomiaki
Syouji
と入力させると

1人目:Tadao
2人目:Tomiaki
3人目:Syouji
と出力させるのが期待している動作です。

以下のプログラムでは1人目の名前を入力した瞬間、

0x5238D3EC (ucrtbased.dll) で例外がスローされました (Cprogramming.c.exe 内): 0xC0000005: 場所 0x01100000 への書き込み中にアクセス違反が発生しました

という文章が表示されました。

c

1#include<stdio.h> 2 3int main(void) 4{ 5 int i,j; 6 char name[3][30]; //最大30文字の名前を3個格納する配列 7 8 for (i = 0; i < 3; i++) { 9 scanf_s("%s", name[i]); 10 } 11 12 for (j = 0; j < 3; j++) { 13 printf("%d人目:%s", j + 1, name[j]); 14 } 15 16 return 0; 17}

どのような点が間違っているのかをどなたか説明していただけないでしょうか。

また、私はC言語の学習を始めて2か月ほどの初心者なので拙い部分も多いかと思います。
質問以外で「ここをこうした方が良い」という改善点がございましたらご指摘していただけると大変嬉しく思います。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/06/28 12:10

エラーが出るなら、そのエラーメッセージをそのままで提示しましょう
cateye

2019/06/28 12:22 編集

>char name[3][30]; //最大30文字の名前を20個格納する配列・・・コメントが違うのですが? ソースを修正する時はコメントの修正も忘れずに・・・・・どっちがバグかわからなくなります。
Cpro

2019/06/28 12:24

申し訳ございません、今後気を付けます。 ご指摘ありがとうございました。
guest

回答4

0

scanf_sをscanfの代わりに使うときのやりかた

ここにのそこらへんの話が載ってますね

そもそも、文字列入力にscanf使うのは禁忌だと思っておきましょう
fgetsつかえばどーです?

投稿2019/06/28 12:13

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cpro

2019/06/28 12:57

回答ありがとうございました。 scanfに文字数を指定した場合、期待した動作をしてくれました。 一つだけ質問なんですが、fgetsの引数を fgets(name[i][30],sizeof(name),stdin); のようにいろいろと試してみたんですが、上手くいきませんでした。 解決策がありましたら教えていただけると嬉しいです。
y_waiwai

2019/06/28 13:08 編集

fgets(name[i],sizeof(name[0]),stdin); ですね。 まあ、scanf_sはオーバーフローしないようにマイクロソフトが作ったもんですんで、そんなに嫌うこともないでしょうけど、既存の関数で同様なことができるんで、そっちを使いたいですね
Cpro

2019/06/28 13:19

fgetsの第一引数が文字配列なので確かにそうなりますね。 解決しました!本当にありがとうございました。
guest

0

ベストアンサー

scanf_s("%s", name[i]);

scanf_s() の書式ってこれで良いのでしょうか?
使った事無いので、調べたら、

scanf_sをscanfの代わりに使うときのやりかた
scanf_s、_scanf_s_l、wscanf_s、_wscanf_s_l

文字列の場合、文字数の指定が必要な様です。
例えば、 scanf_s("%s", name[i], 30);のように。

[追記]
元のコードを、Visual stdio 2019 でコンパイルしたら、エラーになりました。
で、 scanf_s("%s", name[i], 30); としたら、動きました。ただ、

printf("%d人目:%s", j + 1, name[j]);

最後に、改行コード無いので、一行で出力。 最後に、\n を付けましょう。

投稿2019/06/28 12:08

編集2019/06/28 12:13
pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cpro

2019/06/28 13:05

回答ありがとうございました。 本当ですね、上手く動作しました! 一つだけ質問なんですが、scanfの第2引数は変数のアドレスを指定しているので scanf_s("%c",name[i],30) = scanf_s("%c",&name[i][0],30) という解釈でOKですか??(実際に試してみたら後者の書き方でも上手く動作しました)
Cpro

2019/06/28 15:43

ごめんなさい、%cではなく%sの間違いでした… 皆様ありがとうございました。
guest

0

すでに問題自体は解決していますが、質問者にアドバイスを。
この手の質問をすると、scanf() は危険だから使うな、scanf_s() か fgets() を使え、と仰る有識者が何人か出てまいりますが、話半分に聞いとけば良いです。現に、scanf()より安全なはずの scanf_s() を使おうとしたことが例外の原因だった(らしい)という皮肉な結論じゃないですか。

C言語を学び始めたなら、scanf()でもscanf_s()でもfgets() でも、貴方が使いやすい関数を使えばよろしい。scanf() を使うことに遠慮は要らないと思います。scanf() は、入門時期に手ごろな入力関数だから、昔から使われてきたのです。テキストや参考例が scanf() を使っていることも多いので、まずはそのまま動かしてみることが先決。入力手段など、たいていは枝葉末節と割り切れば良い。そのうちもっと良い方法が見つかるでしょうし、scanf() の何が、どう危険なのか、どんな制約があるのかもわかってくるでしょう。それまでは失敗も勉強の内です。

ちなみに、私の手元には scanf_s() が無いので

C

1 for (i = 0; i < 3; i++) { 2 scanf("%s", name[i]); 3 } 4 for (i = 0; i < 3; i++) { 5 printf("%d人目:%s\n", i + 1, name[i]); 6 }

で、問題なく Tadao, Tomoaki, Syouji の3名を入力・表示できたことをお伝えします。念のために言うと、変数「j」は使いませんでした。

なお、

C

1 scanf_s("%c", name[i], 30); 2 scanf_s("%c", &name[i][0], 30);

は、どちらも書き方間違ってますが、一文字入力に限れば問題なく動作するでしょうね。
今の段階で、正しい書き方は何かを確認しておくのは良いことでしょう。
さらに(ここが本題ですが)、間違いなのに動作するのは何故かという問いもあるわけです。まあ、でも、せっかくだから(笑)この手の問いは解決を先延ばしにしておくと後で楽しみが待ってるかもよ、と言っておきます。

投稿2019/06/28 15:37

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cpro

2019/06/28 15:46

回答ありがとうございました。 %cではなく%sの間違いですね…ややこしいことを言って申し訳ないです。 そうなんですか。試行錯誤を繰り返しながら勉強していきます!
pepperleaf

2019/06/29 02:58

確かに危険と言う話は多いですね。 自分も scanf()は使わないですが、単に書式確認が面倒なだけ。fgets()で読み込んで、その後、文字列分解。そうすれば、悩みは少ないと勝手に思っています。セキュリティ的に問題のあるところなら、ともかく、簡単な動作確認なら、入力バッファサイズを 1000バイト位にしておけば、大抵は問題無いと思う。C言語の場合、それ以外にもメモリ破壊の落とし穴は多いので、ご注意を。(昔はそういうトリックの好きな人も居たが)
guest

0

y_waiwaiさんが仰っているようにscanf()危険な関数です。(そのためにMSはscanf_s()などという関数を作ってしまったw)
で、fgets()を使う場合、fgets(name[0],sizeof(name[0]),stdin)などとします。
・・・コンソールから文字列を1個取ってくる関数を作ってしまえばいいのですが・・・
参考:fgets() が改行文字を読み取ると仮定しない

投稿2019/06/28 13:08

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問