質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

Q&A

解決済

1回答

2178閲覧

[C言語] 双方向循環リストにおいて正しい出力が得られません。

apeirogon0813

総合スコア117

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

0グッド

0クリップ

投稿2018/10/21 19:59

編集2018/10/21 20:06

概要

2つの頭(ダミー)がある双方向循環リストにおいて
(1)入力順と同じ順番にリストを作成する
(2)1つ目のリストは要素が奇数、2つ目のリストは要素が偶数のものを消去する
(3)1つめのリストの末尾に2つ目のリストを繋げ、2つ目のリストの末尾に1つ目のリストの先頭ダミーにつなぐ。尚、2つ目の先頭のダミーは消去する。

というものをプログラムをしたいのですが、2つ目のリスト内の要素が偶数のものを消去を行なった後にリストを出力するときに、意図したリストが出力されず、試しに1つ目のリストと同様に要素が奇数のものを消去するように出力すると、これもまた1つ目のリストのようには出力されませんでした。原因がわからないので助けていただきたいです。

発生している問題・エラーメッセージ

入力 1 2 3 4 5 6 にたいして [1][2][3][4][5][6]{6}{5}{4}{3}{2}{1} [1][2][3][4][5][6]{6}{5}{4}{3}{2}{1} [2][3][4][5][6][0]{0}{6}{5}{4}{3}{2} //print_dllist(p) おかしい [2][4][6]{6}{4}{2} //print_dllist(d1)正しい [1][2][3][4]{4}{3}{2}{1} //print_dllist(d2) おかしい [2][4][6]{6}{4}{2}           //print_dllist(d1)当然おかしい と出力され (1)ソースコード上にコメントに記載しているエラー(1)の箇所のprint_dllist(p)の出力が [2][3][4][5][6][1]{1}{6}{5}{4}{3}{2} となってほしいところ [2][3][4][5][6][0]{0}{6}{5}{4}{3}{2} と出力されてしまったこと。 (2)ソースコードのエラー(2)のprint_dllist(d2)の出力が その1つ前の分print_dllist(d1)の出力 [2][4][6]{6}{4}{2} と同様の出力を得るはずが [1][2][3][4]{4}{3}{2}{1} と出力されてしまったとこと、、

該当のソースコード

C

1#include<stdio.h> 2#include<stdlib.h> 3 4typedef int elementtype; 5 6struct dlnode { 7 elementtype element; 8 struct dlnode *prev, *next; 9}; 10 11typedef struct dlnode* dllist; 12 13//nextでたどったリストを[]で囲って出力した後、prevで辿ったリストを{}で囲って出力します 14void print_dllist(dllist d) { 15 dllist n; 16 n = d->next; 17 while(n != d) { 18 printf("[%d]", n->element); 19 n = n->next; 20 } 21 n = n->prev; 22 while(n != d) { 23 printf("{%d}", n->element); 24 n = n->prev; 25 } 26 printf("\n"); 27 28} 29//リストの先頭(ダミー)のprevに追加する(つまり、リストの末尾に追加) 30void insert(dllist p, elementtype e) { 31 dllist n; 32 n = (struct dlnode *) malloc (sizeof (struct dlnode)); 33 n->element = e; 34//空リストの場合(ダミーのみの場合) 35 if(p->next == NULL && p->prev == NULL) { 36 p->prev = n; 37 n->next = p; 38 n->prev = p; 39 p->next = n; 40 } else {//空リストではない場合 41 n->next = p; 42 n->prev = p->prev; 43 p->prev->next = n; 44 p->prev = n; 45 } 46} 47//pが指すノードを消去します。 48void delete(dllist p) { 49 p->prev->next = p->next; 50 p->next->prev = p->prev; 51 free(p); 52} 53//リストd1の末尾にd2を繋げd2の末尾にd1の先頭に繋げ、d2の先頭(ダミー)を解放します 54void append_dllist(dllist d1, dllist d2) { 55 dllist n; 56 n = d1; 57 while(n->next != d1) { 58 n = n->next; 59 } 60 n->next = d2; 61 62 while(n->next != d2) { 63 n = n->next; 64 } 65 n->next = d1; 66 free(d2); 67} 68 69 70int main(void) { 71 int i; 72 char buf[128]; 73 dllist d1, d2, p; 74//空リストの初期化(d1,d2は2つの異なるリスト) 75 d1 = (struct dlnode *)malloc(sizeof(struct dlnode)); 76 d1->prev = NULL; 77 d1->next = NULL; 78 79 d2 = (struct dlnode *)malloc(sizeof(struct dlnode)); 80 d2->prev = NULL; 81 d2->next = NULL; 82 83//入力を得てinsertしていきます 84 while(fgets(buf,sizeof(buf),stdin) != NULL) { 85 sscanf(buf,"%d", &i); 86 insert(d1, i); 87 insert(d2, i); 88 } 89 print_dllist(d1); 90 print_dllist(d2); //これらの出力は正しかった。 91 92///////////////////////////////////////////////////////////////////// 93///ここからの消去操作後のd2の出力がおかしい、 まったくd1と同じことをさせているのに、、//// 94//////////////////////////////////////////////////////////////////// 95 96 p = d1->next; //d1は先頭を示す場所としてとって置きたいためpをnextして動かしていく 97 print_dllist(p);//確認してみたらなぜか出力がおかしい **エラー(1)** 98 while(p != d1) {//一巡するまで 99 if(p->element % 2) { //奇数の場合その要素をもつ節点を消去 100 p = p->next; 101 delete(p->prev); 102 continue; 103 } 104 p = p->next; 105 } 106 107 p = d2->next; 108 while(p != d2) { 109 if(p->element % 2) { //本来はif(!(p->element % 2))とするがデバックのため 110 p = p->next; 111 delete(d2->prev); 112 continue; 113 } 114 p = p->next; 115 } 116 117 print_dllist(d1);//これは正常に出力 118 print_dllist(d2);//なぜかd1と違って誤った出力 **エラー(2)** 119 120 append_dllist(d1, d2); 121 print_dllist(d1); 122 return 0; 123} 124

###入出力例
入力
1
2
3

出力
[1][2][3]{3}{2}{1}
[1][2][3]{3}{2}{1}
[2]{2}
[1][3]{3}{1}
[2][1][3]{3}{1}{2}

入力
2020
-42
8
-888

出力
[2020][-42][8][-888]{-888}{8}{-42}{2020}
[2020][-42][8][-888]{-888}{8}{-42}{2020}
[2020][-42][8][-888]{-888}{8}{-42}{2020}

[2020][-42][8][-888]{-888}{8}{-42}{2020}

補足情報(FW/ツールのバージョンなど)

unix gcc 4.8.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

sscanf(buf,"%d", &i);

リターンのみや数値以外の文字が渡されると変換に失敗してiにゴミが残ります。
代わりにstrtol(3)を使用して変換失敗をチェックして下さい。

p = d1->next; //d1は先頭を示す場所としてとって置きたいためpをnextして動かしていく
print_dllist(p);//確認してみたらなぜか出力がおかしい エラー(1)

print_dllist()は渡された値をダミーの先頭と仮定しています。
d1->nextを渡すと先頭を正しく判定できません。

delete(d2->prev);

"delete(p->prev);"の書き間違い。

投稿2018/10/21 23:09

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apeirogon0813

2018/10/22 03:20

解決しました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問