プロが教える店舗&オフィスのセキュリティ対策術

C言語で、「自然数nを入力し、nの約数をすべて求めて出力後、その個数と合計を出力をする。尚、nとして0(ゼロ)以下が入力されるまで、何度も繰り返す」という問題をやっています。
出力例は、(3を入力したとして)
「3の約数は 1  3
約数の個数は2個
約数の和は4」というものです。

そこで、コーディングをしたのですが、先生が開発したコンパイラで運用したところ、フリーズが起きて強制終了してしまいました。先生は、「そんなことはない。フリーズが起きるときはそのプログラムにバグがあるときだ」と言ってました。

そこでコーディングしたプログラムは以下の通りです。

#include <stdio.h>
main()
{int i,j,n,cnt,sum;
printf("自然数=");scanf("%d",&n);
while(n>=0){
printf("%dの約数は",n);
for(i=1;i<=n;i++){
if(n/i>=0){
j=n/i;
printf(" %d",j);
sum=sum+j;
cnt++;
j=0;}
}
printf("\n");
printf("約数の個数は%d個",cnt);
printf("約数の和は%d",sum);
}}

どこかに間違いがありますか?
IF文の中でいちいちめんどくさいことをしていますが、気にしないでください。

A 回答 (11件中1~10件)

少なくともif(n/i>=0)のところはif(n%i==0)の間違いでないかと思います.


しかしそう考えるとjに関する処理は不要なはず.
jに関する処理は約数を逆順にしているだけということになり,質問の
意味と矛盾しますね.
あとj=0;は無駄な処理のように見えます.
    • good
    • 0

> 先生は、「そんなことはない。

フリーズが起きるときはそのプログラムにバグがあるときだ」と言ってました。

バグのあるプログラムのソースファイルを入力してフリーズするのであれば、そのコンパイラのバグだと思います。
    • good
    • 0

> もしよかったらどこで抜け出すための終了条件を定義すればいいのか教えてください。

。。

scanf を while の中に、判定は、scanf の後、その他は他の方が指摘しているとおり、、、書いたほうが早いか。

main()
{
int i, n, cnt, sum;

while (1) {

printf("自然数="); scanf("%d",&n);
if (n <= 0) { print("done\n"); break; }
cnt = 0; sum = 0;

for (i = 1; i <= n; ++i) {
if (n % i==0) {
sum += i;
cnt++;
}
}
printf("%dの約数は\n", n);
printf("約数の個数は%d個\n", cnt);
printf("約数の和は%d\n\n", sum);
}
return -1;
}
    • good
    • 0

(1)


sumやcntの初期値として、0をセットすることを忘れています。

(2)
jは、n ÷ i の商です。
printfしたりsumに加算するのは、jではなく、iですね。

(3)
約数かどうかの判定は、n ÷ iの余りが0かどうかで調べます。
if (n % i == 0) が正解。
    • good
    • 0

#include <stdio.h>


#include <stdlib.h>
void calc_divisor(void);
void find_by_divisor(struct st_divisor divisor);
unsigned int get_natural_number();
void disp_start(unsigned int number);
void disp_progress(unsigned int find_divisor);
void disp_result(struct st_divisor divisor);
unsigned int str2num(char *str);
struct st_divisor{
  unsigned int sum;
  unsigned int cnt;
  unsigned int (*get_number)(void);
  void (*disp_start)(unsigned int);
  void (*disp_progress)(unsigned int);
  void (*disp_result)(struct st_divisor);
};
int main( void ){
  calc_divisor();
  return 0;
}
void calc_divisor(void){
  struct st_divisor divisor = {
    0,
    0,
    get_natural_number,
    disp_start,
    disp_progress,
    disp_result
  };
  find_by_divisor(divisor);
}
void find_by_divisor(struct st_divisor divisor){
  unsigned int i = 1;
  unsigned int n = divisor.get_number();
  if(divisor.disp_start){divisor.disp_start(n);}
  for( ; i<=n ; i +=1 ) {
    if(n % i == 0 ){
      if(divisor.disp_progress){divisor.disp_progress(i);};
      divisor.sum += i;
      divisor.cnt += 1;
    }
  }
  if(divisor.disp_result){divisor.disp_result(divisor);};
}
unsigned int get_natural_number(){
  char buffer[10] ={0};
  unsigned int number = 0;
  fgets(buffer, 10, stdin);
  number = str2num(buffer);
  if(number <= 0 ){
    printf("不正な入力です。");
    exit(1);
  }
  return number;
}
void disp_start(unsigned int number){
  printf("自然数=%u\n",number);
  printf("%uの約数は",number);
}
void disp_progress(unsigned int find_divisor){
  printf(" %u",find_divisor);
}
void disp_result(struct st_divisor divisor){
  printf("\n");
  printf("約数の個数は%u個\n",divisor.cnt);
  printf("約数の和は%uです。\n",divisor.sum);
}
unsigned int str2num(char *str){
  unsigned int number = 0;
  while(*str){
    if('0' <= *str && *str <= '9'){
      number = number * 10 + *str - '0';
    }else{
     return number;
    }
    str++;
  }
  return number;
}
    • good
    • 0

> for(i=1;i<=n;i++){


> if(n/i>=0){

1≦i≦n の条件では常に
1 ≦ |n/i|
です。(証明省略)

Cで整数同士の割り算の結果は整数(小数点以下切り捨て)なので、 プログラム中のn/iは 数学の|n/i|になります。
つまり、 n/i は常に1以上(ということは0以上)なんで、このif文は常に真です。
よって、if文は必要ありません。自然数n以下の全ての自然数iについて、|n/i|が約数となります。
....って、これ、おかしいですよね?
    • good
    • 0

>どこかに間違いがありますか?



約数というのは、ある整数を割りきることができる数のことですね。
ところが、今のソースコードには「割り切れる(つまり、余りがゼロ)」という
判断をしている箇所が見当たりません。これは致命的です。
    • good
    • 0

>どこかに間違いがありますか?



初心者がフローチャートも書かずにコーディングするところ。
    • good
    • 0

>どこかに間違いがありますか?



cntやsumを初期化していないこと。
定義した時点で「ゼロ」のような特定の値が入ると思ったら大間違いです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

初期化・・・。忘れてました!

ありがとうございます。

お礼日時:2010/07/01 22:12

> while(n>=0){ ... }



このloop、どうやって抜けるんですか?

この回答への補足

回答ありがとうございます。

確かに、無限ループになってます・・・。

もしよかったらどこで抜け出すための終了条件を定義すればいいのか教えてください。。。

補足日時:2010/07/01 22:11
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!