• ベストアンサー

C言語の問題の続き

皆さんに回答してもらったんですがどうしてもうまく書けません。 この問題の鍵となるプログラムを教えてください。 前回URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=100134

質問者が選んだベストアンサー

  • ベストアンサー
  • natural
  • ベストアンサー率37% (419/1115)
回答No.6

naturalです。 補足しておきます。 数学の世界では当たり前のこんな記述「10<x<20」もC言語ではこのような記述「(x>10)で、且つ(x<20)」となります。 つまり1対1の関係で一括りになると言うことですね。 また、こんなことも出来ます。 「(x<11)または(x>19)」(こうすることにより先程の条件の逆になります) 問題は上記の「・・・で、且つ・・・」や「・・・または・・・」の書き方なのですが論理積・論理和というものを使用します。(テキストの索引で調べてみてくださいね) これにより複数の条件を一つの条件式として纏めることが出来ます。 もし論理積・論理和をまだ習っていないのならば使用するのはまずいので、その場合は以下の様にしてみてください。 if(条件1) {   if(条件2)   {     処理;   } } この形でも条件1と条件2を両方満たした場合のみ処理を行うことが可能です。 しかし、もしうっすらとでも論理積等について聞いた覚えがあるのであればこの機会に是非使ってみてください。 ソースが非常にすっきりしますよ。 さて、ここまで書いてきましたが、何処の補足かお判りですよね? 4-3-2の部分の話です。 さらにもう一つヒントを。 先程の例の(x<11)という部分ですが、11の部分を文字定数に置き換えて見てください。 完成形が見えてきませんか? 尚、C言語では以上・以下は「>=」や「<=」になりますのでご注意を。 (注:何れも変数は左辺にあるものと仮定しています) それでは頑張ってください。

ban1123
質問者

お礼

なんとか解けました。ありがとうございました。

その他の回答 (5)

  • natural
  • ベストアンサー率37% (419/1115)
回答No.5

naturalです。 またまたコメント読みました。 そしてまたまた長くなります。 ソースを、と言うことなのですが、これは順序が逆だと思いますよ。(^_^; 途中まででも良いし、間違っていても良いから、まず自分の作ったプログラムを提示して問題点の指摘やヒントを求めるべきだと思います。 授業か研修か判りませんが、普通先にソースは示されないでしょう? 厳しいようですがあなた自身のためだという信念で敢えてソースは書きません。 その代わり1番の時の様にプログラムの流れを書こうと思いますので、まずは自己チェックしてみてください。 では2番の処理の流れを見ていきましょう。 1.変数定義・初期化 2.文字列の入力 3.文字列の長さ測定(長さ用変数に保持) 4.永久ループ |4-1.数値用変数初期化 |4-2.番号入力(番号用文字列変数に入力) |4-3.ループ(番号用文字列の先頭から末尾(ヌル文字)まで) ||4-3-1.数値用変数を10倍する ||4-3-2.現在の文字は数字ではない?(文字定数の範囲で判定) |||4-3-2-1.ループ脱出(内側のループ) ||4-3-3.現在の文字を数値に変換した結果を数値用変数に加算 |4-4.最後に見た文字はヌル文字ではない? ||4-4-1.数字以外の文字の入力があった旨のメッセージを出力 ||4-4-2.永久ループ先頭へ戻る |4-5.数値用変数は長さ用変数の値未満か?(「未満」がポイント) ||4-5-1.永久ループ脱出 |4-6.文字列の範囲外である旨のメッセージ出力 5.結果表示 では解説です。 この問題のポイントはループが2つ存在することです。 入力にエラーがあったときに再入力させるために大きな永久ループで囲います。 その配下に数字かどうかのチェック及び数値への変換のループが入ります。 で、数字かどうかのチェックですが、途中でエラー(つまり数字以外の文字)が見つかった場合はループを抜けます。 ループを抜ける命令、ご存じですよね?(解らなければ補足要求下さい) 勿論途中で引っかからなくても文字列の末尾、ヌル文字まで来れば抜けます。(その場合全て数値への変換処理を通ります) つまりこのループは二通りの抜け方をしてくるわけです。 文字列の途中までとヌル文字まで、何れがエラーかは判りますよね。 ですからこのループを抜けた後で訊いてあげます。 「最後に見た文字はヌル文字ではない?」と。(4-4参照) この条件に引っかかれば数字以外の文字があったと言うことですからエラーメッセージを出力して永久ループ先頭に戻してあげます。 戻す命令はご存じでしょうか?(同じく必要ならば補足要求を) この場所はすでに内側のループの外で永久ループの直下ですので、この命令は永久ループに対して効果を発揮します。 それでは戻されなかった場合の処理の説明を続けます。 この段階で数値への変換が済んでいるはずですから数値が最初に入力された文字列の長さ未満であるか訊きます。 なぜならば文字列の添え字は0から始まるためです。(短い文字列を想定して考えてみてください) この条件に当てはまった場合は全ての入力がOKと言うことですから永久ループを抜けてあげましょう。 抜けられなかったらループ末尾のエラーメッセージの出力を通って自動的に永久ループ先頭に戻ります。 抜けられた場合は結果表示するだけです。 尚、数値への変換は以前書いた回答をもう一度読み返してみてください。 もし理解できなかったらコメント下さい。 それでは頑張ってください。p(^^)q

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.4

> どうしてもうまく書けません。 では、うまく書けなかった、あなたのソースを載せてみてください。 どこが分からないかは、ソースを見れば大体分かりますから。 (もしプログラムを理解したいという意思が無いのであれば、その旨を書かないと答えは書いてもらえないと思いますよ?)

  • natural
  • ベストアンサー率37% (419/1115)
回答No.3

「続き」があるのを知らずに前回の方に補足しちゃいましたんでそちらも見てくださいね~。 取り敢えずどのレベルから「書けない」のかをはっきりさせた方が疑問を解消する近道だと思いますよ。 そのうち全てのソースを書かないといけなくなっちゃいそうな気がするし。 そうそう、loadidentityさん、ban1123さんに教えてあげるロジックとしては高度すぎる気がするのですが・・・。(悪い意味じゃないですよ) この問題が提示されていると言うことはまだプログラミングの初歩を教わっていると思われますので、恐らくこれを書いて持っていくと「自分で解いたのか?」とまず疑われる気がします。 以前社員研修でプログラムを教えていたのでそう思ったのですが・・・。 突然レベルの上がったものを持ってくるとやっぱりわかるものですよ。

ban1123
質問者

補足

1の問題はなんとかできました。ありがとうございました。しかし2の問題が解けません。いちお皆さんの回答をみてそれから考えてるんですがまだ私が勉強していない部分を使って解いてるかもしれないんでソースを書いていただけませんか?そのあとそのソースのわからないところうを質問します。お願いします。

回答No.2

入力回数のカウントには、配列を用いるものとするということなので、 int cnt['Z' - 'A' + 1]; // アルファベット26文字分 int i, len; char s[81]; // 入力領域 memset(cnt, 0x00, sizeof(cnt)); memset(s, 0x00, sizeof(s)); /* ここで領域sにデータを入力 さらに、アルファベットの大文字'A'~'Z'に限定してデータを選別 ここは自力でかんがえてね。 */ /* この時点でバッファには'A'~'Z'までしか格納されてないものとする*/ len = strlen(s); /* 文字数取得 */ for(i = 0; i < len; i++) { cnt[s[i] - 'A']++; /* 数を管理する配列をインクリメント */ }; この例では、 Aを配列のゼロ番目とした数を管理する配列に 各文字の数が管理されます。 なぜなら、コンピュータの世界では 'A'は0x41 つまり 65 という数値で表現されます。 'Z'は0x5a つまり 90。 つまり上の例では 文字領域 s[] の0番目の領域に'B'がいたら... cnt['B' - 'A'] に1プラスします。 言い換えると cnt[66 - 65] は cnt[1]ということなので cnt[1]++ということになります。 お役に立てるでしょうか? わかりずらいときは、また補足してください。

回答No.1

画面からの入力を配列を使って整理するプログラムですよね。 なにが問題を解く障害なのでしょうか? 配列の使い方?文字列の整理方法?画面からの入力? 質問するときは、 どうして解けないのか、何がわからないのか。。。 理由を書かないと、答えることができないよ~。 補足を書くと皆さん答えてくれますよ^^。

ban1123
質問者

補足

回答していただいたことをプログラムでどうやって書いたらいいかがわかりません。

関連するQ&A