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

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

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

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

Q&A

解決済

2回答

2930閲覧

C言語 出力が(NULL)になる

Mellonn

総合スコア3

C

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

0グッド

0クリップ

投稿2021/11/09 09:22

###前提条件
2分木のコードを書いています。
preorderは行きがけ順
inorderは通りがけ順
postorderは帰りがけ順
で各ノードのラベルを出力するプログラムを書こうとしています.

create_tree内で作成したノードのラベルを出力できるのを確認しているのですが,
他のプログラムでは下の実行結果のようになってしまいます。

原因がわからないので,原因または原因の探し方を教えて頂きたいです.

よろしくお願いします.

###実行結果

***:/mnt/c/Users/user/Desktop/***$ make cc -c -o binarytree.o binarytree.c cc binarytree.o main_binarytree.o -o binarytree ***:/mnt/c/Users/user/Desktop/***$ ./binarytree F I D G A L C preorder: (null)(null) inorder: (null)(null) postorder: (null)(null)

###コード
<binarytree.h>

c

1#ifndef INCLUDE_GUARD_BINARYTREE_H 2#define INCLUDE_GUARD_BINARYTREE_H 3 4typedef struct node { 5 char *label; 6 struct node *left; 7 struct node *right; 8} Node; 9 10Node *create_tree(char *label, Node *left, Node *right); 11void preorder(Node *n); 12void inorder(Node *n); 13void postorder(Node *n); 14void display(Node *n); 15void breadth_first_search(Node *n); 16int height(Node *n); 17void delete_tree(Node *n); 18 19#endif // INCLUDE_GUARD_BINARYTREE_H 20

<binarytree.c>

c

1#include <stdio.h> 2#include <stdlib.h> 3#include "binarytree.h" 4 5Node *create_tree(char *label, Node *left, Node *right) 6{ 7 Node *root = (Node*)malloc(sizeof(Node)); 8 9 root->left = (Node*)malloc(sizeof(Node)); 10 root->right = (Node*)malloc(sizeof(Node)); 11 root->label = (char*)malloc(sizeof(char)); 12 13 printf("%s",label); 14 return root; 15} 16 17void preorder(Node *n) 18{ 19 if (n != NULL) 20 { 21 printf("%s",n->label ); 22 preorder(n->left); 23 preorder(n->right); 24 } 25} 26 27void inorder(Node *n) 28{ 29 if (n != NULL) 30 { 31 inorder(n->left); 32 printf("%s",n->label ); 33 inorder(n->right); 34 } 35} 36 37void postorder(Node *n) 38{ 39 if (n != NULL) 40 { 41 postorder(n->left); 42 postorder(n->right); 43 printf("%s",n->label ); 44 } 45} 46

<main_binarytree.c>

c

1#include <stdio.h> 2#include <stdlib.h> 3#include "binarytree.h" 4 5int main(void) { 6 // Build a binary tree 7 Node *f = create_tree("F", NULL, NULL); 8 Node *i = create_tree("I", NULL, NULL); 9 Node *d = create_tree("D", f, NULL); 10 Node *g = create_tree("G", NULL, NULL); 11 Node *a = create_tree("A", i, d); 12 Node *l = create_tree("L", NULL, g); 13 Node *c = create_tree("C", a, l); 14 15 printf("preorder: "); 16 preorder(c); 17 printf("\n"); 18 19 printf("inorder: "); 20 inorder(c); 21 printf("\n"); 22 23 printf("postorder: "); 24 postorder(c); 25 printf("\n"); 26 27return EXIT_SUCCESS; 28}

Makefile

1binarytree: binarytree.o main_binarytree.o

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/11/10 10:31

原因はもう分かっているようなので、原因の探し方だけ。 今回のケースでは最初にNULLが検出されているのが、 preorder: (null)(null) これなので、まずはpreorderを調べます。 関数preorder()の中ではn->labelを参照してprintf()しています。これをデバッガで追っかけてみます。 最初にmain関数のcを引数にpreorder()が呼ばれますが、このときのnは n->label: どこかのアドレス 内容は"" n->left: どこかのアドレス n->left->label: 0x0 n->right: どこかのアドレス n->left->label: 0x0 となっています。すると、cのlabelを出力するときは""なので何も出力されず、n->leftで再帰呼び出しした際に0x0なので(null)が出力され、n->rightで再帰呼び出しした際も0x0で(null)が出力されてしまっていたことが分かります。 次はlabelに""やNULLが入っていた原因を追うことになります。 c->labelやc->left or right->labelを設定しているのはcreate_tree()関数なので、そちらを見てみます。 ここもデバッガで追っかければ分かるのですが、コードを見るだけでlabelはもちろん、メンバ変数に引数で渡された値を全く代入していないことが分かります。そのため、mallocで確保された領域がそのまま使用されており、確保された領域が偶然(?)0だったため、""だったり、NULLだったりしていたということです。 対策としては引数で渡された値を設定すればいいかと思います。渡されたポインタをそのまま代入するか、コピーした内容を作成し、それを設定するかはプログラムの仕様で決めることになります。引数で渡された変数の生存期間と、引数で渡された変数の中身を変更することによりTreeの内容の変更を許すかどうか?によって決まります。
guest

回答2

0

label の型は、char ではなく、char* です。
ポインタですから、そのポインタが指す文字列の領域を確保する必要があります。
strdup は標準ライブラリ関数ではありませんが、多くの処理系で使えます。

C

1#include <string.h> // strdup 2 3Node *create_tree(char *label, Node *left, Node *right) 4{ 5 Node *root = (Node*)malloc(sizeof(Node)); 6 7 root->left = left; 8 root->right = right; 9 root->label = strdup(label); 10 printf("%s",label); 11 return root; 12}

追記
今回、label は "F" のような文字列リテラルなので、strdup は不要でした。
root->label = label; で十分です。strudup が必要になるのは、
次のように同じバッファの文字列を何度も使用する場合でした。

C

1 cahr buf[100]; 2 while (scanf("%s", buf) == 1) { 3 Node *p = create_tree(buf, NULL, NULL);

投稿2021/11/09 12:15

編集2021/11/09 12:42
kazuma-s

総合スコア8224

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

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

Mellonn

2021/11/10 23:27

御回答ありがとうございます. Node型のメモリ領域を開放するのは,Node型の各メンバのメモリを割り当てることと同義という認識でよろしいでしょうか?
kazuma-s

2021/11/11 02:37

Node型のメモリ領域をmallocで「確保」すると、Node型の各メンバのメモリは割り当てられます。 メモリ領域は free で「解放」します。
guest

0

ベストアンサー

create_tree 関数で与えられた引数の値は関数の中でどのように使われているか確認しましょう。

c

1Node *create_tree(char *label, Node *left, Node *right) 2{ 3 Node *root = (Node*)malloc(sizeof(Node)); 4 5 root->left = (Node*)malloc(sizeof(Node)); 6 root->right = (Node*)malloc(sizeof(Node)); 7 root->label = (char*)malloc(sizeof(char)); 8 9 printf("%s",label); 10 return root; 11}

投稿2021/11/09 09:28

mather

総合スコア6759

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

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

Mellonn

2021/11/09 10:42

各引数を入れるための主記憶領域を確保しただけで,その領域に引数を代入していないことが原因だとわかりました。ありがとうございます。 labelはchar型なのでわざわざ確保しなくてよいことも気づきました(なぜなのかはちゃんと説明できませんが...)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問