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

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

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

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

Q&A

解決済

2回答

1056閲覧

プログラムを実行するとSegmentation fault (コアダンプ)と表示されてしまう

KotatsuNeko

総合スコア2

C

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

0グッド

0クリップ

投稿2023/02/22 15:02

編集2023/02/24 15:13

実現したいこと

二分探索木を用いた電話帳検索システムのデータの挿入を行う関数を作成したい。

前提

キーボードから名前と電話番号を入力して二分探索木を構築するプログラムを作成したのですが、実行すると最初の名前と電話番号の入力を行った後にSegmentation fault (コアダンプ)表示されてしまいます。原因と解決方法を教えてください。

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

ノードを追加しますか? [Yes] ==> 1 [No] ==> 0 1 名前を入力してください。 souseki_natsume 電話番号を入力してください。 019-887-8765 Segmentation fault (コアダンプ)

該当のソースコード

c言語

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#define NUMBER 10000 5 6typedef struct node{ 7 char name[NUMBER]; 8 char cellnumb[NUMBER]; 9 struct node *left; 10 struct node *right; 11}Node; 12 13Node *addData(Node *target_node, Node *add_node) 14{ 15 int n; 16 n = strcmp(target_node->name, add_node->name); 17 if(target_node == NULL){ 18 Node *target_node = malloc(sizeof(Node)); 19 strcpy(target_node->name, add_node->name); 20 strcpy(target_node->cellnumb, add_node->cellnumb); 21 target_node->left = NULL; 22 target_node->right = NULL; 23 printf("%s", target_node->name); 24 } 25 else if(n > 0){ 26 target_node->left = addData(target_node->left, add_node); 27 } 28 else if(n < 0){ 29 target_node->right = addData(target_node->right, add_node); 30 } 31 else if(n = 0) 32 printf("同姓同名の人が居ます。\n"); 33 return target_node; 34} 35 36 37int main(void) 38{ 39 int answer; 40 Node *root; 41 Node *p; 42 43 root = NULL; 44 do{ 45 int answer; 46 printf("ノードを追加しますか?\n[Yes] ==> 1 [No] ==> 0\n"); scanf("%d",&answer); 47 if(answer == 1){ 48 printf("名前を入力してください。\n"); scanf("%s", p->name); 49 printf("電話番号を入力してください。\n"); scanf("%s", p->cellnumb); 50 p->left = NULL; 51 p->right = NULL; 52 root = addData(root, p); 53 } 54 }while(answer == 1); 55 56 return 0; 57}

修正後のソースコード

c言語

1 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5#define NUMBER 10000 6 7typedef struct node{ 8 char name[NUMBER]; 9 char cellnumb[NUMBER]; 10 struct node *left; 11 struct node *right; 12}Node; 13 14Node *addData(Node *target_node, Node *add_node) 15{ 16 if(target_node == NULL){ 17 target_node =(Node*)malloc(sizeof(Node)); 18 strcpy(target_node->name, add_node->name); 19 strcpy(target_node->cellnumb, add_node->cellnumb); 20 target_node->left = NULL; 21 target_node->right = NULL; 22 printf("%s", target_node->name); 23 } 24 else if(strcmp(target_node->name, add_node->name) > 0){ 25 target_node->left = addData(target_node->left, add_node); 26 } 27 else if(strcmp(target_node->name, add_node->name) < 0){ 28 target_node->right = addData(target_node->right, add_node); 29 } 30 else 31 printf("同姓同名の人が居ます。\n"); 32 return target_node; 33} 34 35 36int main(void) 37{ 38 int answer; 39 Node *root; 40 Node *p; 41 42 root = NULL; 43 do{ 44 printf("ノードを追加しますか?\n[Yes] ==> 1 [No] ==> 0\n"); scanf("%d",&answer); 45 if(answer == 1){ 46 printf("名前を入力してください。\n"); scanf("%s", p->name); 47 printf("電話番号を入力してください。\n"); scanf("%s", p->cellnumb); 48 p->left = NULL; 49 p->right = NULL; 50 root = addData(root, p); 51 } 52 }while(answer == 1); 53 54 return 0; 55} 56

修正後(2)のソースコード

c言語

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#define NUMBER 10000 5 6typedef struct node{ 7 char name[NUMBER]; 8 char cellnumb[NUMBER]; 9 struct node *left; 10 struct node *right; 11}Node; 12 13Node *addData(Node *add_node, Node *target_node) 14{ 15 if (target_node == NULL){ 16 target_node = malloc(sizeof(Node)); 17 memcpy(target_node, add_node, sizeof(Node)); 18 } 19 else{ 20 int cmp = strcmp(target_node->name, add_node->name); 21 if (cmp > 0) 22 target_node->left = addData(add_node, target_node->left); 23 else if (cmp < 0) 24 target_node->right = addData(add_node, target_node->right); 25 else 26 puts("同姓同名の人が居ます。"); 27 } 28 return target_node; 29} 30 31void showALLData(Node *node) 32{ 33 if(node != NULL){ 34 showALLData(node->left); 35 printf("name : %s cellnumber : %s\n", node->name, node->cellnumb); 36 showALLData(node->right); 37 } 38} 39 40 void freeTree(Node *node) { 41 if(node == NULL) return; 42 freeTree(node->left); 43 freeTree(node->right); 44 free(node); 45 } 46 47int main(void) 48{ 49 int answer; 50 Node *root = NULL; 51 52 do{ 53 printf("ノードを追加しますか?\n[Yes] ==> 1 [No] ==> 0\n"); scanf("%d",&answer); 54 if(answer == 1){ 55 Node p = {0}; 56 printf("名前を入力してください。\n"); scanf("%s", p.name); 57 printf("電話番号を入力してください。\n"); scanf("%s", p.cellnumb); 58 root = addData(&p, root); 59 } 60 showALLData(root); 61 }while(answer == 1); 62 63 freeTree(root); 64 65 return 0; 66} 67

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

teratail はデバッグしてもらう所ではありません。
最初から、各変数の値がどう変化しながら動作していくのかをしっかり意識して追って見てください。

入力時、 p は不定です。
printf("名前を入力してください。\n"); scanf("%s", p->name);
printf("電話番号を入力してください。\n"); scanf("%s", p->cellnumb);
p->left = NULL;
p->right = NULL;
の各 p-> ~ は、何処にアクセスするか分かりません。

addData の最初の呼び出しは、 root は NULL です。
root → target_node で
n = strcmp(target_node->name, add_node->name) を行おうとすれば、 target_node->name はアクセスできません。

ついでに、 main の do-while ループの条件に使っている answer と、追加するかの入力で使っている answer は、スコープが違う別変数です。


malloc を使うなら、同時に free も作っておいたほうが良いです。
結果確認用の表示も必要でしょう。

c

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4 5#define BUFSIZE 1024 6 7typedef struct node { 8 char name[BUFSIZE]; 9 char cellnumb[BUFSIZE]; 10 struct node *left, *right; 11} Node; 12 13Node *addData(Node *target_node, Node *add_node) { 14 if(target_node == NULL) { 15 target_node = malloc(sizeof(Node)); 16 memcpy(target_node, add_node, sizeof(Node)); 17 //printf("%s\n", target_node->name); 18 } else { 19 int cmp = strcmp(target_node->name, add_node->name); 20 if(cmp == 0) { 21 printf("同姓同名の人が居ます。\n"); 22 } else { 23 Node **p = cmp > 0 ? &target_node->left : &target_node->right; 24 *p = addData(*p, add_node); 25 } 26 } 27 return target_node; 28} 29 30void printTree(Node *node, int indent) { 31 if(node == NULL) { 32 for(int i=0; i<indent; i++) printf(" "); 33 if(indent > 0) printf("+"); 34 printf("(null)\n"); 35 } else { 36 printTree(node->left, indent + 2); 37 for(int i=0; i<indent; i++) printf(" "); 38 if(indent > 0) printf("+"); 39 printf("%s\n", node->name); 40 printTree(node->right, indent + 2); 41 } 42} 43 44void freeTree(Node *node) { 45 if(node == NULL) return; 46 freeTree(node->left); 47 freeTree(node->right); 48 free(node); 49} 50 51Node *inputData(Node *root) { 52 Node w = {0}; 53 printf("名前を入力してください。\n"); 54 scanf("%s", w.name); 55 printf("電話番号を入力してください。\n"); 56 scanf("%s\n", w.cellnumb); 57 return addData(root, &w); 58} 59 60int confirm() { 61 int answer; 62 printf("ノードを追加しますか?\n[Yes] ==> 1 [No] ==> 0\n"); 63 scanf("%d", &answer); 64 return answer == 1; 65} 66 67int main(void) { 68 Node *root = NULL; 69 while(confirm()) root = inputData(root); 70 printTree(root, 0); 71 freeTree(root); 72 return 0; 73}

投稿2023/02/22 15:40

編集2023/02/23 10:29
jimbe

総合スコア12545

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

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

KotatsuNeko

2023/02/23 01:33

回答ありがとうございます。今後は具体的な質問ができるようにします。回答を参考に少し修正しました。
jimbe

2023/02/23 07:23 編集

p が不定なのは修正されていません。 scanf が動いているから大丈夫…な訳ではありません。 運が良ければ動き悪ければ異常終了するという、非常に面倒なバグの元です。 またついでですが、 addData の最後の return はインデントが間違っています。
KotatsuNeko

2023/02/24 04:59 編集

丁寧な回答ありがとうございました。回答を参考に修正したところ意図した通りに動作しました。大変助かりました。
guest

0

18行目で、仮引数target_nodeと同名の別の変数target_nodeを宣言してますが、
この変数は18~23行目の範囲だけで有効です。そこに勘違いがあるのでは?
他にもっと間違いがあるのかも知れませんが。

投稿2023/02/22 15:16

otn

総合スコア84423

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

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

otn

2023/02/22 15:38

あと、 > else if(n = 0) 比較なら = じゃなくて == です。= は代入。
KotatsuNeko

2023/02/23 01:33

回答ありがとうございます。少し修正しました。
otn

2023/02/23 03:41

ロジックを追ってみているわけでは無いですが、一見してわかる明らかな間違いはなさそうです。 あとは、1つずつ処理を確認しながらロジックを追うのでしょうか。もしくはデバッガーを使うか。 (このサイズのプログラムなら、机上でロジックを追う方が力が付くと思いますが) 前回・今回の質問のコードの間違いを見ても、記述の意味をちゃんと考えながら書いているようには思えないです。= と == はうっかりミスとしても。 プログラムは書いた通りにしか動かないので、しっかりと意味を考えながら書きましょう。
KotatsuNeko

2023/02/23 16:32

ポインタの理解が追い付いていないので、じっくり考えながら勉強していこうと思います。ありがとうございました。
otn

2023/02/23 16:57

自分で意味をきちんと理解していないコードを書かないと言うことを徹底すれば向上すると思います。 つまり、書こうとするコードを完全に理解できるまで学習するということです。入門書を復習しても良いし、理解するための短いプログラムを自分で書いてみて実行して、予想通りの結果に納得するという方法もあります。予想通りの結果で無い場合は理解のどこかが間違っていることになるので、細かく分解して1ステップずつ進み直します。
KotatsuNeko

2023/02/24 06:13

入門書を復習していこうと思います。丁寧なアドバイスありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問