ポインタや構造体苦手の克服

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Toshita
記事: 23
登録日時: 9年前

ポインタや構造体苦手の克服

#1

投稿記事 by Toshita » 9年前

双方向リストをつくろうとしています。
プログラム歴は半年くらいです。
ポインタや構造体、引数などが苦手で、克服するために
練習しているんですが、よくわからないエラーにひっかかり、
困っています。

0を入力するまでリストに保管し、出力するという感じです。
そこで、LINUXの端末で以下のプログラムをコンパイルしたところ
16行目で「ポインタからキャスト無しに整数を作成している」
17、34、38行目で「ポインタと整数との比較を行なっている」
と出ました。
どちらもどういう意味のエラーかわからず悩んでいます。

コード:

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

struct node{
        int no;
        struct node *next;
        struct node *prev;
}header;
struct node head = &header;

list_maker(void){
        int n;
        struct node *list;

        scanf("%d",&n);
        n = (struct node*)malloc(sizeof(struct node));
        if(n == NULL){
                printf("ERROR-1\n");
                return 0;
        }

        list->no = n;
        list->next = head.next;
        head.next->prev = list;
        list->prev = &head; /*これ何で必要なのか*/
}

int main(void){
        int a=1;
        struct node *list;

        while(a != 0) list->no = list_maker();

        while(list->no != NULL){
                printf("%d",list->no);
                list = list->next;
        }
        while(list->no != NULL){
                printf("%d",list->no);
                list = list->prev;
        }

        return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ポインタや構造体苦手の克服

#2

投稿記事 by みけCAT » 9年前

Toshita さんが書きました:16行目で「ポインタからキャスト無しに整数を作成している」
17、34、38行目で「ポインタと整数との比較を行なっている」
と出ました。
どちらもどういう意味のエラーかわからず悩んでいます。
書いてある通りの意味だと思うのですが…
Toshita さんが書きました:

コード:

struct node head = &header;
構造体(構造体のメンバではない)にポインタを入れようとするのはおかしいです。

コード:

struct node head;
とするべきでしょう。
Toshita さんが書きました:

コード:

list_maker(void){
戻り値の型を明示的に指定することをおすすめします。
Toshita さんが書きました:

コード:

        n = (struct node*)malloc(sizeof(struct node));
        if(n == NULL){
                printf("ERROR-1\n");
                return 0;
        }
せっかく読み込んだnをポインタ(から処理系定義の方法で変換された整数)で上書きしてしまっているので、おかしいでしょう。

コード:

        list = (struct node*)malloc(sizeof(struct node));
        if(list == NULL){
                printf("ERROR-1\n");
                return 0;
        }
とする方がいいでしょう。
Toshita さんが書きました:

コード:

        list->prev = &head; /*これ何で必要なのか*/
そのノードの前のノードがどこかをはっきりさせ、変なところにアクセスしようとしてSegmentation Faultにならないようにするためでしょう。
Toshita さんが書きました:

コード:

        while(a != 0) list->no = list_maker();
これは無限ループになるかもしれません。
さらに、初期化していないlistにアクセスしているのでundefined behaviorであり、Segmentation Faultになるかもしれません。
適切なコードに書き換えた方がいいでしょう。
また、return文を実行せずに最後の}に到達して戻った関数の戻り値を使用することもundefined behaviorです。
Toshita さんが書きました:

コード:

        while(list->no != NULL){
(1個目)

list->noはint型なので、NULLではなく0と比較するべきです。
また、そもそもこのコードはSegmentation Faultになるでしょう。

コード:

        while(list != NULL){
とするべきです。
Toshita さんが書きました:

コード:

        while(list->no != NULL){
(2個目)

1個目と同様に間違っています。
また、仮に1個目をwhile(list != NULL){と修正した場合、
ここではlistは必ずNULLになっているはずなので、ループの中には入りません。
list = list->next;の直前のlistの値を保存して使うなど、工夫が必要でしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ポインタや構造体苦手の克服

#3

投稿記事 by みけCAT » 9年前

修正してみました。
No: 2で指摘した項目のほか、list_maker()中のノードを接続する処理を修正し、メモリを解放する処理を追加しました。

コード:

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

struct node{
        int no;
        struct node *next;
        struct node *prev;
};
struct node head;

int list_maker(void){
        int n;
        struct node *list;

        if(scanf("%d",&n) != 1){
                return 0;
        }
        list = (struct node*)malloc(sizeof(struct node));
        if(list == NULL){
                printf("ERROR-1\n");
                return 0;
        }

        list->no = n;
        list->next = head.next;
        if (head.next != NULL){
                head.next->prev = list;
        }
        head.next = list;
        list->prev = &head;
        return 1;
}

int main(void){
        struct node *list;

        while(list_maker());

        list = head.next;
        while(list != NULL){
                printf("%d",list->no);
                if(list->next == NULL){
                        break;
                }
                list = list->next;
        }
        while(list != NULL && list != &head){
                printf("%d",list->no);
                list = list->prev;
        }

        list = head.next;
        while(list != NULL){
                struct node *next = list->next;
                free(list);
                list = next;
        }
        return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Toshita
記事: 23
登録日時: 9年前

Re: ポインタや構造体苦手の克服

#4

投稿記事 by Toshita » 9年前

懇切丁寧な説明、とても助かりました!
有難うございます。

閉鎖

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