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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

3618閲覧

双方向リストの作成

nanorunamonai

総合スコア34

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/01/11 12:55

編集2016/01/11 13:15

双方向リストの末尾に、ノードを追加する関数を作成したいです。
引数で指定した数だけ、双方向リストの末尾にノードを追加しようとしてます。
以下のコードを実行すると、add_tail関数内のif文 nd = NULLを通り、ノードが追加できません。
原因はなんでしょうか?

C++

1int add_tail(List* nd){ 2 static int num = 0; 3 LIST* addt; 4 addt = (LIST*)malloc(sizeof(LIST)); 5 if(addt == NULL){ 6 cout << "mallco failed" << endl; 7 return -1; 8 } 9 10 if(nd == NULL){ 11 nd = addt; 12 addt->nodeNumber = num++; 13 addt->next = addt; 14 addt->prev = addt; 15 cout << "nd == NULL" << endl; 16 }else{ 17 addt->nodeNumber = num++; 18 nd->prev->next = addt; 19 addt->prev = nd->prev; 20 nd->prev = addt; 21 addt->next = nd; 22 } 23 24 return 0; 25} 26 27int main(int argc, char* argv[]){ 28 if(argc != 2){ 29 cout << "Enter node number." << endl; 30 return -1; 31 } 32 33 LIST* li = NULL; 34 35 int argument=0; 36 37 argument = atoi(argv[1]); 38 39 for(int i=0; i < argument; i++){ 40 add_tail(li); 41 } 42 return 0; 43 44 45}

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

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

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

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

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

guest

回答3

0

こんにちは。

add_tail関数内のif文 nd = NULLを通り

これは、単純にmain()関数内でadd_tail(li);に与えているliがNULLですのでndも常にNULLだからだと思います。
C言語は常に「値渡し」です。ポインタを渡す時もポインタ変数に入っているアドレスが値渡しされます。
従って、add_tail()関数内でndを設定しても、main()関数のliには反映されません。

しかし、仮にそこを訂正しても動作するプログラムになっていないように見えます。
双方向リストの先頭を指すポインタはどれですか?
また、末尾検索している様子がありませんので、末尾を指すポインタもある筈ですね。それはどれですか?
この辺りを明確にすると良いように思います。

投稿2016/01/11 13:44

Chironian

総合スコア23272

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

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

nanorunamonai

2016/01/11 14:21

ご回答ありがとうございます。 add_tail()内で、li(=nd)にポインタを設定しても、反映されないことはわかりました。 双方向リストの先頭と末尾を指すポインタはどこで宣言すれば良いでしょうか? main()内で宣言するか、この質問には記載していませんがヘッダファイル内のクラス 「LIST」のメンバ変数として宣言するべきでしょうか? ご教授願います。。
Chironian

2016/01/11 15:01

あああ、ごめんなさい。 双方向リストの復習がてら調べてみました。 http://www-sens.sys.es.osaka-u.ac.jp/users/shinsaku/lec/computer04/04-0527.pdfの「doubly-linked list(2)」の形式で作られているのですね。 この形式なら、liが先頭ポインタで、先頭ノードのprevポインタが末尾を指してますね。であれば、li管理を適切に行えば動作しそうに見えます。さっきと異なることを言ってごめんなさい。 > 双方向リストの先頭と末尾を指すポインタはどこで宣言すれば良いでしょうか? もし、私が設計する場合は、doubly-linked list(2)ではなくdoubly-linked list(1)の形式を用い、ListクラスとNodeクラスをわけて定義し、Listクラス内に先頭と末尾のポインタやリスト操作用のメソッド群(addNode、insertNode、deleteNodeなどなど)を定義するだろうと思います。 この辺は経験則ですし、状況によってもベターは異なりますので、この設計をお勧めするという意味ではないです。
nanorunamonai

2016/01/12 01:56

双方向"循環"リストですね。 説明不足で申し訳ございません。 クラスを分けるという発想はありませんでした。 考慮してみます。 ありがとうございました。
guest

0

ベストアンサー

ポインタを扱う際に陥りやすい罠ですね。
ポインタ変数を引数にとる関数にポインタを渡した場合、
ポインタが指し示すアドレスのデータは書き換えることができますが、ポインタ変数の値は書き変えることはできません

つまり、今回add_tail関数を

C++

1int add_tail(List** nd) { 2() 3

と定義して関数内部では *nd に対して処理を行い、

C++

1() 2 if(*nd == NULL){ 3 *nd = addt; 4 addt->nodeNumber = num++; 5 addt->next = addt; 6 addt->prev = addt; 7 cout << "nd == NULL" << endl; 8 }else{ 9 addt->nodeNumber = num++; 10 (*nd)->prev->next = addt; 11 addt->prev = (*nd)->prev; 12 (*nd)->prev = addt; 13 addt->next = *nd; 14 } 15 () 16 :

呼び出し側では

C++

1 for(int i=0; i < argument; i++){ 2 add_tail(&li); 3 }

としてやれば先に進めると思います。

投稿2016/01/11 14:24

KoichiSugiyama

総合スコア3041

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

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

nanorunamonai

2016/01/11 14:42

ご回答ありがとうございます。 ポインタが指すデータは書き換え可能、ポインタ自体は書き換え不可能ということですね。 ダブルポインタを用いることで、ポインタndを書き換えることができるということでよろしいでしょうか。 分かりやすい説明ありがとうございました。
guest

0

addt が NULL ということは、その上のmalloc が何かエラーを返していると思います。
まずはmallocに何を渡しているか、sizeof(LIST) を表示してみてはどうでしょうか。

投稿2016/01/11 13:09

yoshi777

総合スコア674

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

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

nanorunamonai

2016/01/11 13:16

申し訳ございません。 addt == NULL ではなく、nd == NULLの方でした。 if(nd == NULL)の時、 nd = addtとして、mallocしたaddtにndを繋いでるんですが、 add_tail()を2回目に実行した時、nd が NULLとなっていしまいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問