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

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

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

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

Q&A

解決済

2回答

2361閲覧

リストを逆順に表示するための関数が、上手く機能しません。

tomokon

総合スコア13

C

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

0グッド

0クリップ

投稿2017/10/21 01:45

編集2017/10/21 03:00

###前提・実現したいこと
Cでノードを使った線形リストを作っており、元からあるリストを逆順に表示するための関数を作っていました。

###発生している問題・エラーメッセージ
逆順に表示するための関数が、想定通りに動作しません。
現在のソースコードでは、例えばリストが{123}であれば{321}と表示したいのに{1}とだけ表示されてしまいます。

###該当のソースコード

lang

1node_t nodeReverse(node_t **ndPtrPtr) 2{ 3 int i = 0; 4 node_t *Pro_ptr1;  5 node_t *Pro_ptr2;  6 while(*ndPtrPtr != NULL){ 7 if(i == 0){ 8 Pro_ptr1 = *ndPtrPtr;         9 ndPtrPtr = &((*ndPtrPtr) -> next); 10 Pro_ptr1 -> next = NULL; 11 }else if(i != 0){ 12 Pro_ptr2 = *ndPtrPtr; 13 ndPtrPtr = &((*ndPtrPtr) -> next); 14 Pro_ptr2 -> next = Pro_ptr1;         15 Pro_ptr1 = Pro_ptr2; 16 }    17 i++; 18 } 19} 20

###関連するソースコード

ノードの定義や、ノードを作成、リストを表示する関数も付記します。 ●ノードの定義 typedef int data_t; typedef struct nodetag { data_t data; struct nodetag *next; }node_t; ●ノードの作成 node_t *nodeNew(data_t dt, node_t *nxt) { node_t *ndPtr; ndPtr = malloc(sizeof(node_t)); if(ndPtr == NULL){ return NULL; }else{ ndPtr -> data = dt; ndPtr -> next = nxt; return ndPtr; } } ●リストにノードを後から加える関数 int nodeAppend(node_t **ndPtrPtr, data_t dt) { node_t *ndPtr; ndPtr = nodeNew(dt, NULL); if(ndPtr == NULL){ return FAILURE; } while(*ndPtrPtr != NULL){ ndPtrPtr = &((*ndPtrPtr) -> next);     } *ndPtrPtr = ndPtr; return SUCCESS; } ●リストの表示 void listPrint(node_t *ndPtr) { printf("{"); while(ndPtr != NULL){ printf("%d", ndPtr -> data); ndPtr = ndPtr -> next; } printf("}\n"); }

###試したこと
ノードごとにある次のノードを示すポインタ変数、nextの値を変更するために、ポインタ変数を二つ作りました。
現在いるノードのアドレスと一つ前のアドレスをそれぞれに格納。それらをそれぞれのノードのnextに逆順に格納していくことで、課題を実現しようとしました。

###補足情報(言語/FW/ツール等のバージョンなど)
使用開発環境:BCC Developer 1.2.21

###最後に
機能をうまく活用できず、分かりにくい表示で最初投稿してしまいました。
申し訳ありません。

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

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

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

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

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

yuki-saito

2017/10/21 02:31 編集

```が閉じられていないのでインデントがなくて見づらいです。プレビューや投稿後に表示確認をしましょう。
tomokon

2017/10/21 02:43

ご指摘、ありがとうございます。すぐに修正し、再度投稿してみます。
yuki-saito

2017/10/21 02:52

はい^^簡単に編集できますので。
Stripe

2017/10/21 06:28

戻り値の型はnode_tでいいんですか? あと、そもそもreturn文が無いようですけど?
tomokon

2017/10/21 16:39

ポインタ変数を使い、関数そのものでリストの変更をしようとしていました。そういったことについても今後は配慮し、ソースコードを書いていければと考えています。
guest

回答2

0

ベストアンサー

ポインタのポインタを参照するなど、不必要に難しく考えられているように思います。
nodeReverse関数を実際にどのように呼びだされているのかがご提示頂いた内容からは不明ですが、もし引数としてnodeNew関数で返却されたnode_tノードのポインタを指定しているのであれば、逆順に入れ替え後のポインタの値は末尾のノードを参照しているために、listPrint関数の出力結果として最後の要素しか出力されていないということが考えられます。
また、mallocで取得したメモリの開放がされていないので、プログラム終了時にfreeを実行されるように変更頂くとよいかと思います。

同じ内容について下記のように考えてみましたので、ご参考まで記載します。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4#define FAILURE 1 5#define SUCCESS 0 6 7typedef int data_t; 8 9typedef struct nodetag 10{ 11 data_t data; 12 struct nodetag *next; 13} node_t; 14 15node_t* nodeReverse(node_t *ndPtr); 16node_t* nodeNew(data_t dt, node_t *nxt); 17int nodeAppend(node_t *ndPtr, data_t dt); 18void listPrint(node_t *ndPtr); 19 20int main(void) 21{ 22 node_t *head; 23 24 head = nodeNew(10, NULL); 25 26 nodeAppend(head, 20); 27 nodeAppend(head, 30); 28 nodeAppend(head, 40); 29 nodeAppend(head, 50); 30 nodeAppend(head, 60); 31 32 listPrint(head); 33 34 head = nodeReverse(head); 35 36 listPrint(head); 37 38 return 0; 39} 40 41node_t* nodeReverse(node_t *ndPtr) 42{ 43 node_t *head, *swap; 44 45 head = ndPtr; 46 while (head->next != NULL) 47 { 48 head = head->next; 49 } 50 51 while (ndPtr != head) 52 { 53 swap = ndPtr->next; 54 if (head->next == NULL) 55 { 56 head->next = ndPtr; 57 ndPtr->next = NULL; 58 } 59 else 60 { 61 ndPtr->next = head->next; 62 head->next = ndPtr; 63 } 64 ndPtr = swap; 65 } 66 67 return head; 68} 69 70node_t* nodeNew(data_t dt, node_t *nxt) 71{ 72 node_t *ndPtr; 73 ndPtr = malloc(sizeof(node_t)); 74 75 if (ndPtr != NULL) 76 { 77 ndPtr->data = dt; 78 ndPtr->next = nxt; 79 } 80 81 return ndPtr; 82} 83 84int nodeAppend(node_t *ndPtr, data_t dt) 85{ 86 node_t *newNode; 87 newNode = nodeNew(dt, NULL); 88 89 if (newNode == NULL) 90 { 91 return FAILURE; 92 } 93 94 while (ndPtr->next != NULL) 95 { 96 ndPtr = ndPtr->next; 97 } 98 99 ndPtr->next = newNode; 100 101 return SUCCESS; 102} 103 104void listPrint(node_t *ndPtr) 105{ 106 printf("{"); 107 while (ndPtr != NULL) 108 { 109 printf("%d,", ndPtr->data); 110 ndPtr = ndPtr->next; 111 } 112 printf("}\n"); 113}

投稿2017/10/21 07:00

編集2017/10/21 07:12
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tomokon

2017/10/21 16:49

回答ありがとうございます。 原因について考察していただき、感謝です。また、ポインタのポインタを使うことが大前提にあったので、ポインタを使うやり方は考えていませんでした。確かにsuyama様のソースコードの方が簡潔で、やりやすいように思えました。是非、参考にさせていただきます。 それとfreeを使うことを指摘して頂き、重ね重ねありがとうございます。 メモリの開放については抜け落ちてしまっていたので、今後、気を付けるようにします。
退会済みユーザー

退会済みユーザー

2017/10/21 17:10 編集

学習のために利用が要件となっている場合などはしかたないかもしれません。 1点だけ追加でアドバイスしますと、 &((*ndPtrPtr) -> next); 上記は下記のように書くこともできます。 &(ndPtrPtr[0]->next); 片方向リストは後戻りがしづらいので、実際の値には配列の添字でアクセスして、 ポインタの参照は動かさない形とした方がすっきり書ける部分もあるかもしれません。 もちろん今回のように都度ノードを作成する場合など、値が連続しているとは限らない場合は利用できないかもしれませんが、最初にいくつかまとめてmallocで領域を取得してノードを作成するなどしておくと連続領域としてアクセスすることができます。 あまり連結リストの勉強にはならないかもしれませんが。
guest

0

解答ではなく考え方のアドバイス(のつもり)です。

紙に{1,2,3}のノードの繋がり具合を四角形と矢印などでかいて、ご自分のコードを実行した際に各変数やノードの繋がり具合がどう変化するか考えてみてください。

イメージ説明

慣れてくれば上の絵のような構造が、処理を1ステップずつ進めるとどう変化するかを頭の中だけでイメージできるのですが、慣れないと「nextを書き換えると構造はこうかわる、次にこうすると・・・」みたいなことを考えているうちに構造がどう変化するかがこんがらがってきます。最初は面倒でも一々紙に書いた方が分かり易いですよ。

投稿2017/10/21 06:31

編集2017/10/21 17:22
KSwordOfHaste

総合スコア18394

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

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

tomokon

2017/10/21 16:41

回答ありがとうございます。 アドバイス、大切にさせていただきます。実際まだまだ頭の中でこんがらがることが多いので、図を書いてどうプログラムが動くのかをイメージするようにしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問