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

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

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

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

解決済

c言語双方向循環リスト番兵ノードについて

pocomi
pocomi

総合スコア2

C

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

3回答

0グッド

0クリップ

711閲覧

投稿2022/05/11 04:54

編集2022/05/11 07:07

現在双方向循環リストでrotateをする関数を書いてるのですが、-1である番兵ノードがどうしても出力されてしまい、番兵ノードを出力しない出力方法が思いつきません。
どなたかアドバイスを頂きたいです。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4struct t_node { 5 struct t_node *next; 6 struct t_node *prev; 7 int data; 8}; 9struct t_node *first_node(int data) { 10 struct t_node *head; 11 head = malloc(sizeof(struct t_node *)); 12 head->next = head; 13 head->prev = head; 14 head->data = data; 15} 16void add_back(struct t_node *list, int data) { 17 struct t_node *node; 18 struct t_node *p = list; 19 node = malloc(sizeof(struct t_node *)); 20 if (node == NULL) 21 return; 22 while (p->next != list) { 23 p = p->next; 24 } 25 p->next->prev = node; 26 p->next = node; 27 node->prev = p; 28 node->data = data; 29 node->next = list; 30} 31void print(struct t_node *head) { 32 struct t_node *tmp; 33 if (head == NULL) 34 return; 35 tmp = head->next; 36 printf("tmp data is %d\n", tmp->data);//5 37 printf("head data is %d\n", head->data);//1 38 while (tmp != head) { 39 printf("%d ", tmp->data); 40 tmp = tmp->next; 41 } 42 printf("%d", tmp->data); 43 printf("\n"); 44} 45void swap(struct t_node *n1, struct t_node *n2) { 46 int tmp; 47 tmp = n1->data; 48 n1->data = n2->data; 49 n2->data = tmp; 50} 51void rotate(struct t_node *list_head) { 52 struct t_node *change_list_head_next; 53 struct t_node *head; 54 struct t_node *last; 55 first_node(0); 56 change_list_head_next = list_head->next; 57 swap(change_list_head_next, list_head); 58 head = list_head->next; 59 last = head->prev; 60 print(head->next); 61 return; 62} 63int main(void) { 64 struct t_node *list_head; 65 struct t_node *change_list_head_next; 66 list_head = NULL; 67 list_head = first_node(-1); 68 add_back(list_head, 3); 69 add_back(list_head, 1); 70 add_back(list_head, 5); 71 print(list_head); 72 rotate(list_head); 73}

出力結果
-1を消したい。

C

13 1 5 -1 25 3 -1 1

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

ozwk

2022/05/11 05:16

実行するとコアダンプ(Illegal instruction (core dumped))が発生して出力結果を得るどころではありません。 おそらくコードを貼り間違えていますので修正してください
melian

2022/05/11 05:36

ところで、memory sanitizer 付きでコンパイルして実行すると、 head = malloc(sizeof(struct t_node *)); と node = malloc(sizeof(struct t_node *)); の直後で heap buffer overflow が発生します。理由は、、明白ですよね。
episteme

2022/05/11 05:52

関数:first_node() が t_node* を返していません。

回答3

2

折角の双方向リストなのですから、 head->prev を使ったり、循環をノードの(先頭と最後で)移動で行ったりしては如何でしょうか。
(というより、そうしないと双方向リストを使う意味が無いのでは。)

c

1#include <stdio.h> 2#include <stdlib.h> 3 4typedef struct t_node { 5 struct t_node *next; 6 struct t_node *prev; 7 int data; 8} Node; 9 10void initPointers(Node *node) { 11 node->next = node; 12 node->prev = node; 13} 14 15Node *createNode(int data) { 16 Node *node = malloc(sizeof(Node)); 17 if(node == NULL) return NULL; //error 18 initPointers(node); 19 node->data = data; 20 return node; 21} 22//最後に追加 23void addLast(Node *head, Node *node) { 24 Node *last = head->prev; 25 node->prev = last; 26 node->next = head; 27 last->next = node; 28 head->prev = node; 29} 30//先頭に追加 31void addFirst(Node *head, Node *node) { 32 Node *first = head->next; 33 node->prev = head; 34 node->next = first; 35 head->next = node; 36 first->prev = node; 37} 38//最後を削除 39Node *removeLast(Node *head) { 40 if(head->prev == head) return NULL; 41 Node *last = head->prev; 42 head->prev = last->prev; 43 last->prev->next = head; 44 initPointers(last); 45 return last; 46} 47//最初を削除 48Node *removeFirst(Node *head) { 49 if(head->next == head) return NULL; 50 Node *first = head->next; 51 head->next = first->next; 52 first->next->prev = head; 53 initPointers(first); 54 return first; 55} 56 57void print(Node *head) { 58 for(Node *p = head->next; p != head; p = p->next) { 59 printf("%d ", p->data); 60 } 61 printf("\n"); 62} 63 64void rotateRight(Node *head) { 65 Node *last = removeLast(head); 66 if(last != NULL) addFirst(head, last); 67} 68void rotateLeft(Node *head) { 69 Node *first = removeFirst(head); 70 if(first != NULL) addLast(head, first); 71} 72 73int main(void) { 74 Node *head = createNode(-1); 75 76 addLast(head, createNode(3)); 77 addLast(head, createNode(1)); 78 addLast(head, createNode(5)); 79 print(head); 80 81 //rotateLeft(head); 82 rotateRight(head); 83 print(head); 84}

plain

13 1 5 25 3 1

ikedas さんご提案の構造にしてみました。テストも追加。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4typedef struct t_node { 5 struct t_node *next; 6 struct t_node *prev; 7 int data; 8} Node; 9 10Node *createNode(int data) { 11 Node *node = malloc(sizeof(Node)); 12 if(node == NULL) return NULL; //error 13 node->next = NULL; 14 node->prev = NULL; 15 node->data = data; 16 return node; 17} 18//最後に追加 19void addLast(Node **head, Node *node) { 20 if(*head == NULL) { //データ無し 21 *head = node; 22 node->next = node; 23 node->prev = node; 24 } else { 25 node->next = *head; 26 node->prev = (*head)->prev; 27 node->next->prev = node; 28 node->prev->next = node; 29 } 30} 31 32void print(Node *head) { 33 Node *p = head; 34 if(p != NULL) { 35 do { 36 printf("%d ", p->data); 37 } while((p = p->next) != head); 38 } 39 printf("\n"); 40} 41 42void rotateRight(Node **head) { 43 if(*head != NULL) *head = (*head)->next; 44} 45void rotateLeft(Node **head) { 46 if(*head != NULL) *head = (*head)->prev; 47} 48 49int main(void) { 50 Node *head = NULL; 51 52 addLast(&head, createNode(3)); 53 addLast(&head, createNode(1)); 54 addLast(&head, createNode(5)); 55 print(head); 56 57 rotateRight(&head); //右へ1回 58 print(head); 59 60 addLast(&head, createNode(7)); //7を追加して 61 print(head); 62 63 rotateLeft(&head); //左へ2回 64 rotateLeft(&head); 65 print(head); 66}

plain

13 1 5 25 3 1 35 3 1 7 41 7 5 3

投稿2022/05/11 07:13

編集2022/05/11 19:20
jimbe

総合スコア10741

ikedas, pocomi👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

ikedas

2022/05/11 09:11

というか循環リストなので、リストを変更しなくても``head->prev``や``head->next``が求めるものになっているとも思います。
jimbe

2022/05/11 18:31

head が循環の中に含まない、 3,1,5 のノードだけで循環するようにすれば、 head の位置をずらすだけになりますね。

1

ベストアンサー

番兵ノードを設ける理由は、リスト上のノードを渡り歩く際にリスト終端の判定を簡単にしたりするためだと思います。

しかしご提示のコードでは、各関数のループの条件がadd_back()ではp->next != listprint()ではtmp != headとなっていて、関数の引数として与えられたノードに達するとループが停止するようになっています。このように停止すべきノードが毎回与えられるのならば、番兵のような特別なノードはいらないですよね。

つまり、最初にfirst_node()で作成するノードも番兵ノードではなく普通のノードだと考えられますから、出力しないようにする必要はないです。


ご質問の点にのみ回答しました。現在のコードを上記のように変えただけで意図した通りの動作をするのかどうかについては確認していません。

投稿2022/05/11 06:03

ikedas

総合スコア3130

pocomi👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

Java

1void print(struct t_node *head) { 2 struct t_node *tmp; 3 if (head == NULL) 4 return; 5 tmp = head->next; 6 printf("tmp data is %d\n", tmp->data);//5 7 printf("head data is %d\n", head->data);//1 8 while (tmp != head) { 9 printf("%d ", tmp->data); 10 tmp = tmp->next; 11 } 12 printf("%d", tmp->data); // ここでもprintfするのはなぜ? 13 printf("\n"); 14}

投稿2022/05/11 04:57

episteme

総合スコア15980

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

pocomi

2022/05/11 05:01

printf("%d", tmp->data); // ここでもprintfするのはなぜ? 出力結果にある最後の1が出力されなくなってしまうのでprintfで出力しています。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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