🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

セグメンテーション違反

セグメンテーション違反とは、ソフトウェア実行時に発生するエラーのひとつであり、許可されていないメモリにアクセスしたときに起きます。しばしば、ポインタの不適切な使用、またはバッファオーバーフローによって起こります。

Q&A

解決済

2回答

2083閲覧

c言語 再帰を用いたリスト構造でのエラー

tamintya

総合スコア34

C

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

セグメンテーション違反

セグメンテーション違反とは、ソフトウェア実行時に発生するエラーのひとつであり、許可されていないメモリにアクセスしたときに起きます。しばしば、ポインタの不適切な使用、またはバッファオーバーフローによって起こります。

0グッド

0クリップ

投稿2021/06/04 16:26

### 正しく値が表示されるようにしたい

c言語で正の整数を入力し小さい順に並べるというリスト構造を再帰を用いて作りたいのですが以下の問題が発生してしまいます。
10行目の (*q)->data = a; がうまく作動していないのことがわかったのですがうまく行きません。
原因と解決法を教えてほしいです。

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

正の値の入力しても何も表示されない。 負の値を入力するとセグメンテーションエラーが発生する。 (例) 0以上のデータを入力して下さい(負の値で終了) -->4 0以上のデータを入力して下さい(負の値で終了) -->-1 セグメンテーション違反です

該当のソースコード

c

1#include<stdio.h> 2#include<stdlib.h> 3 4struct cell{ 5 double data; 6 struct cell *next; 7}; 8 9void add_list(struct cell **q, double a){ 10 if((*q)->next == NULL){ 11 (*q)->data = a; 12 } 13 if((*q)->data < a){ 14 add_list(&(*q)->next,a); 15 } 16 else{ 17 (*q)->data = a; 18 } 19} 20 21void show_list(struct cell **q ){ 22 if((*q)->next == NULL){ 23 printf("\n"); 24 } 25 else{ 26 printf("-> %lf" , (*q)->data); 27 show_list(&(*q)->next); 28 } 29} 30 31void free_list(struct cell *q ){ 32 if(q->next != NULL){ 33 free_list(q->next); 34 } 35 free(q); 36} 37 38 39int main(void){ 40 double data; 41 struct cell *p; 42 (*p).next = NULL; 43 44 while(1){ 45 printf("0以上のデータを入力して下さい(負の値で終了) -->"); 46 scanf("%lf" , &data); 47 if(data < 0){ 48 free_list(p); 49 } 50 else{ 51 add_list(&p,data); 52 show_list(&p); 53 } 54 55 } 56 57 return 0; 58} 59

試したこと

gdbコマンドによる値の確認

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

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

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

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

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

guest

回答2

0

C言語のコードを書くなら、デバッグ環境を整えましょう。
WindowsならVisualStudio、Eclipseなど、
ソースコードの任意の場所で実行を止め、変数のナカミを確認できます。
また、ワンステップづつ実行させてコードの動きを確認できます

そうすれば、どこが間違ってるのかわからない、という質問をせずに済むようになります

投稿2021/06/04 22:41

y_waiwai

総合スコア88038

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

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

kazuma-s

2021/06/05 01:18

質問者は gdb を使っていると書いています。 gdb では、任意の場所で実行を止めて、変数の中身を確認できます。 ステップ実行でコードの動きを確認できます。
y_waiwai

2021/06/05 01:24

と、あなたは言ってても、質問者はそれができていないってことですね 使いこなせない難しいものより、もっと簡単にできる方法があるんですから、それをおしえてあげましょう
guest

0

ベストアンサー

main から実行を開始して、
struct cell *p; で宣言した p は初期化されていません。
(*p).next = NULL;(*p) はでたらめなメモリ領域の struct cell です。
ここで、セグメンテーションフォールトになっても仕方がないのに、偶然どこかの
メモリ領域の struct cell の next に NULL を書き込めてしまったようです。

あと、malloc で領域を確保していないのに free をするのも変です。

追記
現在のコードはどうなっているのですか?
質問に追記してください。
malloc は使っていますか?

また、次のコードを参考にして、あなたのコードに活用できませんか?

C

1#include <stdio.h> // scanf, printf 2#include <stdlib.h> // malloc, free 3 4struct cell { 5 double data; 6 struct cell *next; 7}; 8 9void add_list(struct cell **q, double a) 10{ 11 if (*q != NULL && (*q)->data < a) 12 add_list(&(*q)->next, a); 13 else { 14 struct cell *p = malloc(sizeof(struct cell)); 15 p->data = a; 16 p->next = *q; 17 *q = p; 18 } 19} 20 21void show_list(struct cell *p) 22{ 23 if (p == NULL) 24 printf("\n"); 25 else { 26 printf(" -> %g", p->data); 27 show_list(p->next); 28 } 29} 30 31void free_list(struct cell *p) 32{ 33 if (p == NULL) return; 34 free_list(p->next); 35 free(p); 36} 37 38int main(void) 39{ 40 double data; 41 struct cell *p = NULL; 42 43 while (1) { 44 printf("0以上のデータを入力して下さい(負の値で終了) -->"); 45 if (scanf("%lf", &data) != 1 || data < 0) break; 46 add_list(&p, data); 47 show_list(p); 48 } 49 free_list(p); 50 return 0; 51}

このコードで分からないところはどこですか?

投稿2021/06/04 17:13

編集2021/06/05 16:13
kazuma-s

総合スコア8224

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

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

tamintya

2021/06/05 02:46

回答ありがとうございます。 ご指摘の部分を  p = NULL と書き直したのですがうまくいきません。 直し方が間違っているのでしょうか?
tamintya

2021/06/05 02:49

また値の比較を行うつもりの if((*q)->data < a )の部分でエラーが起きているようなのですが この書き方が間違っているのでしょうか?
kazuma-s

2021/06/05 02:50

p を NULL にしたら、*p は何ですか? p = malloc(sizeof(struct cell)); として、領域を確保してからでないと、 (*p).next = NULL; はできません。(*p).next は p->next と書けます。
kazuma-s

2021/06/05 08:53

> if((*q)->data < a )の部分でエラーが起きているようなのですが 変数の値を見ていますか? (gdb) p q (gdb) p *q (gdb) p (*q)->data
tamintya

2021/06/05 14:29

指摘のおかげで(*q)->data などにほしい値を入力することはできました。 しかし入力時に(*q)->next が NULL になっているため show_list で改行を行ってしまうのですが その対処が分かりません。  教えてほしいです。
tamintya

2021/06/05 15:49

追記ありがとうございます。 本日は予定があるため確認して月曜日に返信させてもらいます。
tamintya

2021/06/07 10:23

ソースコードを理解することは出来たのですが実行してみると "show_list"内の"p->data"や"p->next"がアクセスエラーが発生してしまいます。 main関数内の"p"では正しく表示されているので原因が分かりません。
tamintya

2021/06/07 10:25

ソースコードは回答してくださったものとほぼ同じです。
kazuma-s

2021/06/07 15:05

実行したときの入力データは何ですか? 「ほぼ同じ」と「全く同じ」は違います。 その違いでアクセスエラーになっているのではありませんか? また、私が最初に書いたコードには不備があったので、修正を入れています。 私の最新のコードを試していますか?
tamintya

2021/06/08 13:06

コードを参考にmain内の *p に初期値として NULL を代入したところ正常に作動するようになったのですがなぜNULL を代入しないとセグメンテーション違反が発生するのでしょうか。
kazuma-s

2021/06/08 13:21

私にはあなたの修正内容が正確には分かりません。 セグメンテーション違反が発生するコードと入力データを質問に追記してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問