• 締切済み

C言語のC++で質問です。

初めまして。 学籍番号から入力した数字がいくつあるか検索して検索結果を表示するプログラムを作っているのですが、このプログラムには制約がありまして、 ・while,do~while文を使用する ・for文、配列は使えない(習っていないため) ・if文は使用可能 ずっと試行錯誤してるのですがwhile文を使って表現することができません。 どなたか分かる方いたら教えてください、よろしくお願いします。 以下プログラムソース #include<stdio.h> int main() { int no,i; int gakuseki,mono; int no1,no2,no3,no4,no5,no6,no7; int kari1,kari2,kari3,kari4,kari5,kari6,kari7; mono=0; i=1; printf("任意の数字:"); scanf("%d",&no); printf("学籍番号:"); scanf("%d",&gakuseki); kari1=gakuseki/1000000; kari2=gakuseki/100000; kari3=gakuseki/10000; kari4=gakuseki/1000; kari5=gakuseki/100; kari6=gakuseki/10; kari7=gakuseki/1; no1=kari1; no2=(kari2)-(kari1*10);  no3=(kari3)-(kari2*10); no4=(kari4)-(kari3*10); no5=(kari5)-(kari4*10); no6=(kari6)-(kari5*10); no7=(kari7)-(kari6*10);   /*学籍番号を桁ごとに分解する*/ printf("%d\n",no1);  printf("%d\n",no2); printf("%d\n",no3); printf("%d\n",no4); printf("%d\n",no5); printf("%d\n",no6); printf("%d\n",no7); /*検索*/ if(no==no1) { mono=mono+1; } if(no==no2) { mono=mono+1; } if(no==no3) { mono=mono+1; } if(no==no4) { mono=mono+1; } if(no==no5) { mono=mono+1; } if(no==no6) { mono=mono+1; } if(no==no7) { mono=mono+1; } if(mono>=1) { printf("数字%dは%d個あります\n",no,mono); } else printf("数字%dはありません\n",no); return(0); } 【実行結果】 任意の数字:3 学籍番号:0653123 0 6 5 3 1 2 3 数字1は1つあります。 【実行結果ここまで】 if文で一つ一つ書いてたらすごく長くなってしまいました。 ここをどうにかwhile文でかけたらうまくいくかもしれないのですが・・・。

みんなの回答

noname#144013
noname#144013
回答No.10

度々すみません。#6&#9です #7&#9の件ですが、#5さんの言われているのは、たぶん【学籍番号】の先頭の"0"を有効とするか、 無効とするかという問題(#8さんの言われているゼロパディング、ゼロサプレスと同様)のようですね。 先頭の"0"を無効とする場合は、確かに#6のソースでは不一致となってしまいますね。 ※7桁固定&ゼロパディング限定と明記しておけば良かったですね。すみませんでした。m(__)m

noname#144013
noname#144013
回答No.9

#5さん、こんにちは。#6です。 私の開発環境【Windows98SE+Visual C++ Ver 5.0】(だいぶ古いですが。^_^;)では、no=0 の 場合でも上手くいっている(というかオリジナルソースの実行結果と同じ)のですが、#5さんの 環境ではダメなのでしょうか? 具体的にどこで失敗していますか? 宜しければ今後の参考のために教えて頂けないでしょうか? 以下は、質問者さんのオリジナルソースでの実行結果と、#6のソースでの実行結果です。 (※プロンプト画面の表示結果をコピー&ペーストしたものです。) ■実行結果(オリジナルソースの場合) 【1】 任意の数字:0 学籍番号:0000000 0 0 0 0 0 0 0 数字0は7個あります 【2】 任意の数字:0 学籍番号:1234560 1 2 3 4 5 6 0 数字0は1個あります 【3】 任意の数字:0 学籍番号:0123456 0 1 2 3 4 5 6 数字0は1個あります 【4】 任意の数字:0 学籍番号:1203450 1 2 0 3 4 5 0 数字0は2個あります ■実行結果(#6のソースの場合) 【1】 任意の数字(数値:0~9):0 学籍番号 (数値:0~9999999):0000000 学籍番号(桁毎): [0],[0],[0],[0],[0],[0],[0] 結果:数字[0]は 7個あります 【2】 任意の数字(数値:0~9):0 学籍番号 (数値:0~9999999):1234560 学籍番号(桁毎): [1],[2],[3],[4],[5],[6],[0] 結果:数字[0]は 1個あります 【3】 任意の数字(数値:0~9):0 学籍番号 (数値:0~9999999):0123456 学籍番号(桁毎): [0],[1],[2],[3],[4],[5],[6] 結果:数字[0]は 1個あります 【4】 任意の数字(数値:0~9):0 学籍番号 (数値:0~9999999):1203450 学籍番号(桁毎): [1],[2],[0],[3],[4],[5],[0] 結果:数字[0]は 2個あります

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.8

>ずっと試行錯誤してるのですがwhile文を使って表現することができません。  学籍番号の各桁数字は「使い捨て(◆)」でいいのでは? ☆お示しのソース・実行結果をみると、学籍番号は「7桁限定」ですね。  極端な話、任意の数字が0で、学籍番号0000001の場合は、  「数字0は6個あります」  と出るのが「正解」ですね。 ☆7桁以内の学籍番号(ゼロパディング、ゼロサプレス双方)に対応するソースを・・。  (Borland C++5.6.4) #include<stdio.h> int main( void ) {  int iKazu, iGakuseki, iKeta = 7;  int iCnt = 0;  printf( "任意の数字:" );  scanf( "%d", &iKazu );  iKazu %= 10; // おまじない?  printf( "学籍番号:" );  scanf( "%d", &iGakuseki ); // ゼロパディング無意味  while( iKeta-- ){   if( iKazu == ( iGakuseki % 10 ) ) iCnt++; // ◆下位から   printf( "%d %d %d\n", iKeta, ( iGakuseki % 10 ), iCnt );   iGakuseki /= 10; // 上位へ  }  printf( "数字 %d は %d 個あります\n", iKazu, iCnt );  return( 0 ); } 注:インデントに全角空白を用いています。タブに一括変換して下さい。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.7

#5です。 #6さんへ noとして、0を入れた時におかしくなりませんか?

noname#144013
noname#144013
回答No.6

こんにちは。 #2さんと#5さんの案の合わせ技になりますが、サンプルコードを作ってみました。 ※#2さんと#5さんに感謝致します。有り難う御座いました。m(__)m ほんとは、具体的なソースコードそのままは書かない方が良いかもしれませんが、 他人のソースを見て学べること(良くも悪くも)もあると思いますので載せてみました。 注)【任意の数字】は整数1桁まで(0~9)、【学籍番号】は整数7桁まで(0~9999999)   という前提条件で作成しています。 ■サンプルコード /* * サンプル:[学籍番号]内の該当数値検出 * *【使用している命令】 * if, while *【使用している標準関数】 * printf, scanf */ #include <stdio.h> int main() { int no, gakuseki, mono; int gakuseki2; int div, syou, amari; int err = 0; /* データ入力 */ printf("任意の数字(数値:0~9):"); scanf("%d",&no); printf("学籍番号 (数値:0~9999999):"); scanf("%d",&gakuseki); /* 入力値のチェック */ if(err==0 && (no<0 || no>9)) err=1; if(err==0 && (gakuseki<0 || gakuseki>9999999)) err=2; if(err!=0){ printf("##%03d: Input Error!!\n", err); return 1; } /* [学籍番号]から[任意の数字]を検出(桁毎の表示付き) */ printf("学籍番号(桁毎): "); mono = 0; gakuseki2 = gakuseki; div = 1000000; while(div!=0){ syou = (gakuseki2 / div); /* 【商】計算 */ //amari = (gakuseki2 % div); /* 【余り】計算(演算子[%]を使って良い場合) */ amari = gakuseki2 - (syou * div); /* 【余り】計算(演算子[%]を使えない場合) */ if(syou == no) mono++; printf("[%d]%s", syou, (div!=1? ",":"\n")); gakuseki2 = amari; div /= 10; } /* 検出結果の表示 */ if(mono>=1){ printf("結果:数字[%d]は %d個あります\n",no,mono); } else{ printf("結果:数字[%d]はありません\n",no); } return (0); } ■実行結果 任意の数字(数値:0~9):3 学籍番号 (数値:0~9999999):0653123 学籍番号(桁毎): [0],[6],[5],[3],[1],[2],[3] 結果:数字[3]は 2個あります 以上です。参考にして頂ければ幸いです。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

配列を使わなくても書けますね。 今は、各桁の数値を予め計算してますが、これをwhileの中でひとつずつ計算するようにすればいいんです。 「余り」を使うのが肝心ですね。 一番下の桁は、 gakuseki%10 で、求まります。 次の桁は gakuseki/=10; とした後、 gakuseki%10 で求まります。 次の桁も同じく、 gakuseki/=10; とした後、 gakuseki%10 で求まります。 whileでできそうな気がしませんか?

回答No.4

#include <stdio.h> int main(void) { int i, j, k = 0; printf("任意の数字 : "); if((i = getchar()) == '\n'){ puts("??"); return 1; } else while(getchar() != '\n') ; printf("学籍番号 : "); while((j = getchar()) != '\n') k += (i == j); if(k) printf("数字 %c は %d個あります\n", i, k); else printf("数字 %c はありません\n", i); return 0; }

hinata-h
質問者

お礼

yaemon_2006さん、回答ありがとうございます。 返信が遅くなってすみません。 実際にそのプログラムを動作させてみたところ動きました。 しかし最初のif文とwhile文がよく分からないのですが、iを任意の数字と置き換えて比較するのが\nとありますがこの\nっていうのは改行であってますでしょうか? while文に関して、jは学籍番号と置き換えてそれが\nと違ったらkの値がどうなるのかって感じで解釈しているのですが。 k+=(i==j)の辺りも詳しく教えてくださると助かります。 サンプルプログラム本当にありがとうございます。

  • pick52
  • ベストアンサー率35% (166/466)
回答No.3

> ・for文、配列は使えない(習っていないため) というのは「使ってはダメ(禁止)」ということなのでしょうか。 もし、単に使い方が分からないから使えないということでしたら、 自分で調べて使えるようになってください。 現在では、ネット上でいくらでも調べることができます。 というより、ループ使っている時点で配列を利用しないのは無駄ですし、 whileよりも配列の方が先に学習することのはずなのですけど。 (ループ処理は配列を処理するために利用する場合がほとんど) whileの使い方より配列やforの方がずっと簡単で分かりやすいと思います。

hinata-h
質問者

お礼

pick52さん、回答ありがとうございます。 返信が遅くなってすみません。 そうですね、使ってはいけないという意味だと思います。 for文につきましてはwhile文の後 配列につきましてはfor文の後という順番になってまして(教科書通りの順番)読んでいるとこれは使ったほうが早いような感じです。 while文を講義で行っていてその時出された問題なのでwhile文を使ってのことだと思います。

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.2

割り算の余りを使っていいのだったら、 (1)学籍番号を10で割った余りが入力数値と等しければカウントアップ。 (2)学籍番号を10で割った商を学籍番号に入れなおす。 これをwhileで学籍番号の桁数分繰り返す。 って感じでいけるんじゃないでしょうか? 学籍番号の各桁を表示しなくてもいいとか、桁の小さい順に表示してもよいの だったらこれで問題なさそう。 各桁を桁の大きい順に表示しなければならないのだったら、 (1)学籍番号を10のn乗で割った商が入力数値と等しければカウントアップ。 (2)学籍番号から上記の商×10のn乗を減算する。 これをwhileでnを1づつ減らしながら繰り返す。 (n乗を習ってないのだったら、割る数を1000000からループするごとに10割っていけばよい) ていう感じでできそう。

hinata-h
質問者

お礼

Lchan0211さん、回答ありがとうございます。 返信が遅れてすみません。 最初の案で実際にやってみたところなんとかwhile文で動かすことができました。 学籍番号の桁は7桁指定でした。説明が足りなくてすみません。 後格桁表示は上手く取り出せているか心配だったので表示させてみたのですが、紛らわしくて本当にすみません。

  • snowize
  • ベストアンサー率27% (68/245)
回答No.1

どこがC++なのかは分かりませんが、配列が使えないという時点でちまちまちんたら長くなるのは必然でしょう(苦笑)。何のために配列があるのかと考えたら、こういうたらたらしたソースを書きたくないからってのがひとつなんですからw

hinata-h
質問者

お礼

snowizeさん C言語の間違いでした。Visual Basic6.0で開いていたため勘違いをしました。 配列に関しては正直使いたいんですけど。。

関連するQ&A