C言語関係掲示板

過去ログ

No.1212 線形リストをもちいた素数の出力

[戻る] [ホームページ]
No.15965

線形リストをもちいた素数の出力
投稿者---ます(2004/07/28 16:59:19)


線形リストを用い、素数を出力させるというプログラムで悩んでいます。素数かどうかを判定する際に、線形リストに保存されている素数のみを利用しなければいけないのです。次のようなプログラムを変形すれば求まるらしいのですが…。

#include <stdio.h>
#include <stdlib.h>

#define MAX 5

typedef struct data Data;
typedef struct data *DataP;

struct data{
int val;
DataP prev;
};

DataP add_data(int i,DataP last);
void print_data(DataP last);
void free_list(DataP last);

int main()
{
int i;
DataP last = NULL;

for(i=0;i<MAX;++i){
last = add_data(i,last);
}

print_data(last);
free_list(last);
exit(0);
}

DataP add_data(int i,DataP last)
{
DataP new;
if((new = (DataP)malloc(sizeof(Data))) == NULL){
fprintf(stderr,"data allocation error !\n");
exit(1);
}
new -> val = i;
new -> prev = last;
return new;
}

void print_data(DataP last)
{
while(last != NULL){
printf("output data %d\n",last -> val);
last = last -> prev;
}
}

void free_list(DataP last)
{
DataP olast;

while(last != NULL){
olast = last;
last = last -> prev;
free(olast);
}
}



No.15967

Re:線形リストをもちいた素数の出力
投稿者---ぽこ(2004/07/28 17:08:47)


>線形リストを用い、素数を出力させるというプログラムで悩んでいます。
>素数かどうかを判定する際に、線形リストに保存されている素数のみを利
>用しなければいけないのです。次のようなプログラムを変形すれば求まる
>らしいのですが…。

問題は分かりましたが、問題点が分かりません。
どこでつまずいているのでしょうか?


No.15969

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/28 17:40:58)


>問題は分かりましたが、問題点が分かりません。
>どこでつまずいているのでしょうか?

DataP add_dataの中で、前の線形リストに保存されている数でiを割り、その余りが0でなければ、さらに前の線形リストに保存されている数でiを割る、といった事を繰り返して、途中で余りが0になるようならそれは素数ではなく、保存せずに次の数に進み、0にならないようならそれが素数であり、それを保存して、次の数に進むといったプログラムを作ろうとしたのです。このようなプログラムの作り方がわからないのです。
説明がわかりにくくて申し訳ないのですが、よろしくお願いします。


No.15970

Re:線形リストをもちいた素数の出力
投稿者---ぽこ(2004/07/28 18:29:00)


>このようなプログラムの作り方がわからないのです。

プログラムの作り方ですが、
まず、ますさんが説明されたことを、if文や、while文、日本語等を使って
処理の流れを書いてみてはどうでしょうか?
例えば、

if(明日雨なら){
  テレビを見る。
  return;
}else{
  買い物に行く。
}

/* 買い物にて */
while(希望の値段より高い){
  値引き交渉をやる
}

といった感じで。



No.15972

Re:線形リストをもちいた素数の出力
投稿者---ぽへぇ(2004/07/28 18:56:05)


気が付いたこと
● MAXが5になっていますが、素数の動作チェックなら
  もうちょっと大きい方がいいですね。
● i =0 から始まっていますが、まずいことが起こるので
    最小の素数(2)から始めましょう。
というのは、
>前の線形リストに保存されている数でiを割り、その余りが0でなければ
0から始めた場合、リストにまず0が保存されます。
次のループで1を0で割ろうとして…0で割ることはできませんからね。
また 1 も全ての数を割り切ってしまいますからこれも除外します。
結局2から始めたほうが良い、ということになります。

余りを求めるのは % 演算子を使います。
線形リストをたどる方法はわかりますか? > ます さん




No.15975

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/28 22:17:53)


>線形リストをたどる方法はわかりますか? > ます さん

線形リストというものをちゃんと理解できず、たどる方法もいまいちわかりません。
last=last->prev
で、たどれるのでしょうか?



No.15985

Re:線形リストをもちいた素数の出力
投稿者---ぽへぇ(2004/07/29 06:16:25)


>last=last->prev
>で、たどれるのでしょうか?
たどれます。これは「線形リストを前にたどって」います。
print_data と free_listにお手本が書いてありましたね。

次に、「繰り返し」はわかりますか?
素数を求めるには、今まで保存した要素(ノード)を全部
たどる必要があります。リストを最後までたどるには
どうしたら良いでしょうか? (表現としては「リストの
最前」の方が適切か)
 これもprint_data と free_listにお手本が書いてあります。



No.15988

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/29 13:32:26)


>次に、「繰り返し」はわかりますか?
>素数を求めるには、今まで保存した要素(ノード)を全部
>たどる必要があります。リストを最後までたどるには
>どうしたら良いでしょうか? (表現としては「リストの
>最前」の方が適切か)
>これもprint_data と free_listにお手本が書いてあります。

while(last!=NULL)のなかで、last=last->prevを使えば良いのですね。
ありがとうございます。
これを使って、頑張ってみたいと思います。


No.15993

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/29 17:51:19)


add_dataの中で、次のようなプログラムを作ったところ、99が表示されてしましました…。なぜなのですか?

DataP add_data(int i,DataP last)
{
DataP new;
if((new = (DataP)malloc(sizeof(Data))) == NULL){
fprintf(stderr,"data allocation error !\n");
exit(1);
}
while(last!=NULL){
if(i%last->val!=0){
last=last->prev;
}
else{
i+=i;
}
}
if(last==NULL){
new->val=i;>prev=last;
}
return new;
}


No.15994

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/29 17:53:51)


すいません、下のプログラムの間違いでした。

DataP add_data(int i,DataP last)
{
DataP new;
if((new = (DataP)malloc(sizeof(Data))) == NULL){
fprintf(stderr,"data allocation error !\n");
exit(1);
}
while(last!=NULL){
if(i%last->val!=0){
last=last->prev;
}
else{
i+=i;
}
}
if(last==NULL){
new->val=i;
new>prev=last;
}
return new;
}


No.15997

Re:線形リストをもちいた素数の出力
投稿者---REE(2004/07/29 19:05:56)


※ソースの添付は「HTML変換ツール」で字下げ!

if(i%last->val!=0){
    last=last->prev;
}
else{
    i+=i;
}

この i+=i; は何でしょう?



No.16001

Re:線形リストをもちいた素数の出力
投稿者---ぽへぇ(2004/07/29 21:00:08)


>   while(last!=NULL){
(中略)
>   }
このすぐ下で

>   if(last==NULL){
>      new->val=i;
>      new>prev=last;
>   }
とlastを使ってます。(コピペは正確に。new->prev=last;でしょう?)
結果、new->prevにNULLが代入されます。
これは上のwhileでlastを使ってしまったのが原因です。

ヒント1:別の変数に last をコピーして判定を繰り返すのがいいでしょう。
ヒント2:繰り返し部分は「余りが0なら繰り返しを打ち切る」という
 書き方にすると楽かもね。
ヒント3:
>   if((new = (DataP)malloc(sizeof(Data))) == NULL){
>      fprintf(stderr,"data allocation error !\n");
>      exit(1);
>   }
この部分がどういう意味か説明できますか?
この部分が必要なのは「ある条件」が成立したときだけ
ではなかったでしょうか? だとしたら、関数の冒頭に書く必要はありますか?



No.16005

Re:線形リストをもちいた素数の出力
投稿者---ます(2004/07/30 13:14:03)


>ヒント1:別の変数に last をコピーして判定を繰り返すのがいいでしょう。
>ヒント2:繰り返し部分は「余りが0なら繰り返しを打ち切る」という
 書き方にすると楽かもね。

ヒントを基に、自分なりに次のようなものを作ってみたのですが、数値を入れて実行するとエラーになってしまいます。

DataP add_data(int i,DataP last)
{
    DataP new;
    DataP n=last;
    if((new = (DataP)malloc(sizeof(Data))) == NULL){
        fprintf(stderr,"data allocation error !\n");
        exit(1);
    }
    while(i%n->val!=0){
        last=last->prev;
    }
    if(n==NULL){
        new->val=i;
        new->prev=last;
    }
    return new;
}


>ヒント3:
>> if((new = (DataP)malloc(sizeof(Data))) == NULL){
>> fprintf(stderr,"data allocation error !\n");
>> exit(1);
>> }
>この部分がどういう意味か説明できますか?

正直、ちゃんと理解できていません。どのような意味なのでしょうか?


No.16011

Re:線形リストをもちいた素数の出力
投稿者---ぽへぇ(2004/07/30 18:23:01)


>>ヒント3:
>> if((new = (DataP)malloc(sizeof(Data))) == NULL){
>>この部分がどういう意味か説明できますか?
>正直、ちゃんと理解できていません。どのような意味なのでしょうか?

mallocはわかりますか?
http://www9.plala.or.jp/sgwr-t/lib/malloc.html
を参照してください。

>    while(i % n->val != 0){
>        last=last->prev;
>    }
私の前のレスで
>これは上のwhileでlastを使ってしまったのが原因です。
と書いたのを思い出してください。

リスト構造を理解するところから始めたほうが良いかと思います。
http://www9.plala.or.jp/sgwr-t/c/sec15-5.html
あたりを参照してください。
(mallocと組み合わせて使った例が載っています)



No.16026

Re:線形リストをもちいた素数の出力
投稿者---ぽへぇ(2004/07/31 19:29:07)


これが唯一の正解というわけではないでしょうが、ご参考まで。

DataP add_data(int i, DataP last)
{
    DataP   newp;
    DataP   n = last;

    while (n != NULL) {
        if (i % n->val == 0) {
            /* 検索を打ち切る */
            break;
        }
        n = n->prev;
    }
    if (n == NULL) { /* if (!n) とも書く */
        /* 素数だったのでリストに追加 */
        if ((newp = (DataP)malloc(sizeof(Data))) == NULL){
            fprintf(stderr,"data allocation error !\n");
            exit(1);
        }
        newp->val = i;
        newp->prev = last;
    } else {
        /* リストを変更しないでそのまま返す */
        newp = last;
    }
    return newp;
}