リスト構造プログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
buttrfly

リスト構造プログラムについて

#1

投稿記事 by buttrfly » 15年前

初めまして、学校でプログラムを勉強しています
プログラム初心者です
私は今学校の課題でリスト構造のプログラムを作成しています
仕様は以下のとおりです

・テキストファイルより1行(255字以内)受け取りリスト構造に追加する
・リスト構造は昇順に追加する( 順序はstrcmp()仕様による )
・テキストファイルを表示する
・リスト構造追加後の結果を表示する

プログラム自体はできあがっているのですが
エラーが取れません
作成したプログラムは以下の通りです

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

typedef struct list{
    struct list *next;
    char str[256];
}ELEMENT;

int main (void){
    
    FILE *fp;
    struct ELEMENT *root = NULL;
    struct ELEMENT *elem,*pos,*work;
    int i;
    
    if(fp = fopen("strings.dat","r") == NULL){
        printf("ファイルを開けません\n");
        exit(1);
    }
    
    while(!feof(fp)){
        if(elem = (ELEMENT*) malloc(sizeof(ELEMENT)) == NULL){
            printf("メモリ割り当てエラー\n");
            exit(1);
        }
        
        fgets(elem->str , 255 , fp);   // 1行取得
        printf("%s" , elem->str);
        
        if(root == NULL){        // 空だった場合
            elem->next = NULL;
            root = elem;
        }else{
            pos = root;
            
            while(pos != NULL){
                i = strcmp(elem->str , pos->str);
                
                if(i < 0) break;
                
                work = pos;
                pos = pos->next;
            }
            
            if(pos == NULL){        // 最後尾に追加
                elem->next = NULL;
                pos->next = elem;
            }else if(pos == root){     // 先頭に追加
                elem->next = pos;
                root = elem;
            }else{             // 間に追加
                elem->next = pos;
                work->next = elem;
            }
        }
    }
    
    fclose(fp);
    work = root;
    
    while(work != NULL){
        pos = work->next;
        printf("%s",work->str);
        free(work);
        work = pos;
    }
    
    return 0;
}

使用しているコンパイラは独習Cに付属しているGNU C Compilerです
出るエラーは以下のものです

list.c: In function `main':
list.c:16: warning: assignment makes pointer from integer without a cast
list.c:22: warning: assignment makes pointer from integer without a cast
list.c:27: error: dereferencing pointer to incomplete type
list.c:28: error: dereferencing pointer to incomplete type
list.c:31: error: dereferencing pointer to incomplete type
list.c:37: error: dereferencing pointer to incomplete type
list.c:37: error: dereferencing pointer to incomplete type
list.c:42: error: dereferencing pointer to incomplete type
list.c:46: error: dereferencing pointer to incomplete type
list.c:47: error: dereferencing pointer to incomplete type
list.c:49: error: dereferencing pointer to incomplete type
list.c:52: error: dereferencing pointer to incomplete type
list.c:53: error: dereferencing pointer to incomplete type
list.c:62: error: dereferencing pointer to incomplete type
list.c:63: error: dereferencing pointer to incomplete type


このエラーの意味はなんなのでしょうか?
どうかご教授お願いいたします

sizuma

Re:リスト構造プログラムについて

#2

投稿記事 by sizuma » 15年前

全角スペースでソースを編集をしませんでしたか?
修正するのが面倒です。


最初の方の警告は演算子の優先度順で評価されるので、動かないですね
fp = fopen("strings.dat","r") == NULL
これは
(fp = fopen("strings.dat","r")) == NULL
としましょう。
その下のエラーチェックもですね。

実行するとエラーがでるんで、どっかバグがあります。
探してみてください。

最初の警告は
右側の整数型をキャストしないでポインタに変えてるよ。
下は多分ポインタが参照してるものがないよって意味だと思います。
fpには1か0が格納されてますからね。

box

Re:リスト構造プログラムについて

#3

投稿記事 by box » 15年前

> プログラム自体はできあがっているのですが
> エラーが取れません

コンパイルも通っていないプログラムを「できあがった」とは言いません。

> typedef struct list{
> struct list *next;
> char str[256];
> }ELEMENT;

struct listに対してELEMENTという別名を付けているのですから、

> struct ELEMENT *root = NULL;
> struct ELEMENT *elem,*pos,*work;

ここでstructと書く必要はありません。
これと、sizumaさんの回答に対応すると、コンパイルエラーは
おそらく出なくなるでしょう。

ここで、やっと実行ファイルができますが、
まだ「プログラムができあがった」とは言いません。
実行して予想どおりの結果を得ることができて、
初めて「できあがった」と言います。
画像

sizuma

Re:リスト構造プログラムについて

#4

投稿記事 by sizuma » 15年前

>structと書く必要はありません。
あぁ、本当ですね。
全角削除するときに自然に消してました^^;

buttrfly

Re:リスト構造プログラムについて

#5

投稿記事 by buttrfly » 15年前

返信遅れすみません

とりあえずコンパイルエラーはなくなりました
お二人ともありがとうございます


>コンパイルも通っていないプログラムを「できあがった」とは言いません
>ここで、やっと実行ファイルができますが、
>まだ「プログラムができあがった」とは言いません。
>実行して予想どおりの結果を得ることができて、
>初めて「できあがった」と言います。

ごもっともです・・;



コンパイルは通ったのですが
実行すると2行目を表示して止まってしまいました
これはどうしてなのでしょうか?

書き直したプログラムは下のとおりです
割り当ての部分は()で括るとややこしくなったので
別に分けました
あと、全角も消しました
ご迷惑をお掛けします;
#include <stdio.h>
#include <stdlib.h>

typedef struct list{
    struct list *next;
    char str[256];
}ELEMENT;

int main (void){
    
    FILE *fp;
    ELEMENT *root = NULL;
    ELEMENT *elem,*pos,*work;
    int i;
    
    if((fp = fopen("strings.dat","r")) == NULL){        // ファイルを開く
        printf("ファイルを開けません\n");
        exit(1);
    }
    
    while(!feof(fp)){
        
        elem = (ELEMENT*) malloc(sizeof(ELEMENT));        // メモリ割当
        
        if(!elem){
            printf("メモリ割り当てエラー\n");
            exit(1);
        }
        
        fgets(elem->str , 256 , fp);                    // 1行取得
        printf("%s" , elem->str);
        
        if(root == NULL){                                // 中身が空
            elem->next = NULL;
            root = elem;
        }else{
            pos = root;
            
            while(pos != NULL){
                i = strcmp(elem->str , pos->str);
                
                if(i < 0) break;
                
                work = pos;
                pos = pos->next;
            }
            
            if(pos == NULL){                        // 最後尾に追加
                elem->next = NULL;
                pos->next = elem;
            }else if(pos == root){                    // 先頭に追加
                elem->next = pos;
                root = elem;
            }else{                                    // 間に追加
                elem->next = pos;
                work->next = elem;
            }
        }
    }
    
    fclose(fp);
    work = root;
    
    while(work != NULL){
        pos = work->next;
        printf("%s",work->str);                    // 結果を表示
        free(work);                                // メモリ解放
        work = pos;
    }
    
    return 0;
}

non

Re:リスト構造プログラムについて

#6

投稿記事 by non » 15年前

if(pos == NULL){                        // 最後尾に追加
                elem->next = NULL;
                pos->next = elem;
この部分はまずいですね。

それと、
feofを使うと、EOFになったときに、ゴミをprintfで出力することになる
から、感心しないなぁ。

buttrfly

Re:リスト構造プログラムについて

#7

投稿記事 by buttrfly » 15年前

> この部分はまずいですね。

どうまずいのかを具体的に示して頂けるとありがたいのですけれど


> feofを使うと、EOFになったときに、ゴミをprintfで出力することになる
> から、感心しないなぁ。

ゴミとはどういうことでしょうか?

non

Re:リスト構造プログラムについて

#8

投稿記事 by non » 15年前

>pos->next = elem;

pos==NULLならpos->nextなんてないでしょう。

>ゴミ
ゴミがでないなら、私の勘違いでしょう。
試してないので・・・

non

Re:リスト構造プログラムについて

#9

投稿記事 by non » 15年前

やっぱり、ゴミが出そうですね。
http://msdn.microsoft.com/ja-jp/library/xssktc6e.aspx
解説部分を読んでください。

box

Re:リスト構造プログラムについて

#10

投稿記事 by box » 15年前

リスト構造を実装するとき、図を使うと早く完成するかもしれません。
頭の中だけでは、ポインターのつなぎ替えがなかなかうまくいかないような気がします。

buttrfly

Re:リスト構造プログラムについて

#11

投稿記事 by buttrfly » 15年前

> pos==NULLならpos->nextなんてないでしょう。
ごもっともです
work->nextが正しいですね
feofについてもわかりました
ありがとうございました


> リスト構造を実装するとき、図を使うと早く完成するかもしれません。
> 頭の中だけでは、ポインターのつなぎ替えがなかなかうまくいかないような気がします。
一応学校課題の関係でプログラムをPCで打つ前に
紙に疑似言語で書いているのでトレースするときに図に書いては散々やったんですが・・;



エラーもなく無事に表示されるようになりました
feofのゴミについては自分なりに考えて条件文を変えてみようと思います
回答をいただいた皆様ありがとうございました

閉鎖

“C言語何でも質問掲示板” へ戻る