ページ 11

scanf文について

Posted: 2010年9月14日(火) 19:11
by べの
はじめまして。
C言語の勉強を始めて2日目になります。

http://wisdom.sakura.ne.jp/programming/c/c7.html
↑こちらのサイトを参考に進めているのですが、
このページの例にあるswitch文の定数式が整数(partAとします)、文字定数(partBとします)のとき

partAのみの場合 →正常動作
partBのみの場合 →正常動作
partA+partBの場合 →不具合
partB+partAの場合 →正常動作

となってしまいます。
具体的には、partBがpartAの後ろにくる場合のみ、scanf("%c" , &ch); が実行されず、defaultが返ってきてしまいます。
scanfを記述する順序によって問題が発生しているのでしょうか?
問題点、解決法をご教授ください。
宜しくお願い致します。


■環境
WindowsXP Home SP3
Microsoft Visual C++ 2010 Express

■ソース
#include <stdio.h>

int main()

{
char ch;
int var;


/* partA ここから */
printf("あなたは猫耳が好きですか?\n");
printf("はい = 1\tいいえ = 2\t兎耳のほうが… = 3\n");

scanf("%d",&var);

switch (var) {
case 1:
printf("同士よ、共に全宇宙を猫耳に染めようぞ!\n\n");
break;
case 2:
printf("それじゃアキバは歩けないぜ、旦那\n\n");
break;
case 3:
printf("ウサギちゃんか…耳で空飛ぶんだぞ!\n\n");
break;
default:
printf("指定した数を選択してください\n\n");
}
/* partA ここまで */


/* partB ここから */
printf("今日の奈美はどこかおかしい\n突然不安にかられた僕は…\n\n");
printf("A\t「奈美ぃーー!どこだ、返事をしろー!!」\n");
printf("\t僕は奈美を必死で探した\n\n");
printf("B\t「猫耳ィー!どこだ、でじこーーー!!」\n");
printf("\t僕は男のロマンを叫んだ\n");


switch(ch) {
case 'A':
printf("まぁ、何をしたって屋敷は燃えるんだよね…\n僕はプレイヤーとして諦めた\n\n");
break;
case 'B':
printf("やはりこの世で最も美しいのは猫耳だ\n今日、改めてそれを確信した\n\n");
break;
default:
printf("AかBを選択してにょ\n\n");
}
/* partB ここまで */


getchar();
return 0;
}

Re:scanf文について

Posted: 2010年9月14日(火) 19:21
by パコネコ
chの代入はどこに?

Re:scanf文について

Posted: 2010年9月14日(火) 19:22
by Dixq (管理人)
> べのさん

chの入力はどこで行っています?

でも大体予想は付きます。
恐らく原因はこの辺だと思います。

http://www.google.co.jp/search?hl=ja&q= ... lr=lang_ja

最初は解らないですよね。
scanfは便利なのですが、何かと良く苦労させられます。

Re:scanf文について

Posted: 2010年9月14日(火) 19:38
by べの
>パコネコさん
>Dixgさん

すみません、説明文に載せるときにコピーではなくカットしてしまったようです・・・
こんな初歩的なミスをするとは・・

位置はPartBのswitch文の直前になります。



ご回答ありがとうございます。
入力が残っているということがあるのですね。
なぜそういうことが起こるのかについては調べてみようと思います。
ありがとうございました。

-----------------------
折角なので、タイトルとは関係ありませんが便乗してもうひとつ質問させてください。
上記のソースでたとえると、switch文のdefault時には再度入力をやりなおさせるのが普通だと思うのです。
素人考えではGOTO(のようなもの)を使いpartの頭まで戻せばよいと思っていたのですが
Cでは通常GOTOは使ってはいけないと書いてありました。
この場合はwhileを使い以下のような処理でよいのでしょうか。一応正常に動作はします。
よろしくお願い致します。


/* partA ここから */

while (1) {
printf("あなたは猫耳が好きですか?\n");
printf("はい = 1\tいいえ = 2\t兎耳のほうが… = 3\n");

scanf("%d",&var);

switch (var) {
case 1:
printf("同士よ、共に全宇宙を猫耳に染めようぞ!\n\n");
break;
case 2:
printf("それじゃアキバは歩けないぜ、旦那\n\n");
break;
case 3:
printf("ウサギちゃんか…耳で空飛ぶんだぞ!\n\n");
break;
default:
printf("指定した数を選択してください\n\n");
continue;
}
break;
}
/* partA ここまで */

Re:scanf文について

Posted: 2010年9月14日(火) 19:54
by たかぎ
> 素人考えではGOTO(のようなもの)を使いpartの頭まで戻せばよいと思っていたのですが
> Cでは通常GOTOは使ってはいけないと書いてありました。

再試行に(GOTOではなく)gotoを使うのは、わりと普通のことです。

Re:scanf文について

Posted: 2010年9月14日(火) 20:02
by Dixq (管理人)
scanfやprintfってC言語の最初に学ぶ事ですが、実はすごく色んな機能があります。
最初に沢山の機能を紹介しても混乱するかもしれませんが、scanfはwikiっても出てきて参考になります。
http://ja.wikipedia.org/wiki/Scanf

(・・ってたかぎさんのHPが脚注に載っている^^;)

適切な入力については考え始めるとキリがないので、
まだC言語歴2日目であれば、今は「出来たらいいや」で良いと思います。

やり直しの方法については良いと思いますよ。

Re:scanf文について

Posted: 2010年9月14日(火) 20:08
by Dixq (管理人)
2重ループから抜けたり、関数の中で終了処理をあちこちでする必要がある場合など、
gotoを使う事はありますね。

ただ、C言語の参考サイト、参考書にはgotoは使わないようにと書いてあると思います。
恐らくプログラムの歴史的にgotoが難解なプログラムを生み出したという経緯がある為、むやみに使うなということになっているのだと思います。

gotoは使い方次第で酷いプログラムにも良いプログラムにもなりますが、
使い方をしっかり理解しないで使うと前者になりがちです。
また、gotoを書かなければ実行できない処理はありません。

ですから、初心者のうちは使わないようにと教えるのが一般的になっているものと思います。


# 今月号のinterfaceにプログラムの歴史的な事が書いてありました。
http://interface.cqpub.co.jp/
gotoが何故悪いかという例も色々書いてあって面白かったので、よければどうぞ。

Re:scanf文について

Posted: 2010年9月14日(火) 20:37
by べの
色々とありがとうございます。
まだこんなレベルではありますが、今後も行き詰ることがあればお世話になるかと思います。
宜しくお願い致します。

Re:scanf文について

Posted: 2010年9月14日(火) 20:46
by たかぎ
> gotoは使い方次第で酷いプログラムにも良いプログラムにもなりますが、
> 使い方をしっかり理解しないで使うと前者になりがちです。

そういうことです。
なお、gotoを使わないままでいると、いつまでたっても使いこなせるようにはなりません。
使える状況では(失敗覚悟ででも)使ってみることをお勧めします。
どんな言語機能も、使いこなせなければ酷いプログラムの量産につながるだけですので、実際に使ってみて、失敗しながら身につける方がよいのです。

> また、gotoを書かなければ実行できない処理はありません。

その代わり、制御の流れを(本来必要ないはずの)フラグ等の変数に依存することになってしまいます。
また、その論法でいけば、ifとgotoを使えばすべての制御構造は記述できるので、for文もwhile文もdo文もswitch文も不要になります。
現実にはそんなことはないので、やはり適材適所なのでしょう(多くの場合、技術的なことではなく、人員の力量に左右されることが多いのが困りものですが...)。

ちなみに、gotoの濫用で酷くなったプログラムというのは、昔のBASICなど、関数内のローカルなgotoではなく、グローバルなgotoによって生み出されました。
構造化プログラミングでは、(ローカルな)gotoを使ったコーディングではなく、(グローバルな)goto文という言語仕様の導入が禁止なのだと思います。

Re:scanf文について

Posted: 2010年9月14日(火) 20:46
by box
どこからも指摘がなかったようですが、
scanf「文」ではなくてscanf「関数」です。