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

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

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

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

セグメント

セグメントは、複数の連続するIPアドレスをまとめて ひとつのネットワークとして一度にアクセスできる領域のことです。

Q&A

解決済

4回答

1628閲覧

連結リストで該当したものをprintしながら捜査をつづけたい

German_p0tat0

総合スコア26

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

セグメント

セグメントは、複数の連続するIPアドレスをまとめて ひとつのネットワークとして一度にアクセスできる領域のことです。

0グッド

0クリップ

投稿2020/07/27 16:56

編集2020/07/28 18:22

現状説明

txtの情報を連結リストに格納して、郵便番号を入力するとその郵便番号と住所と何件表示されたかを出力するプログラムを作っています。
実行すると

郵便番号を入力してください:0
プログラムを終了します
%

上のように2回目以降0件見つかりましたと検索できなくなります。

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

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

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

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

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

KoichiSugiyama

2020/07/27 17:09

エラーメッセージが出力されているのでしたら、コピー&ペーストで貼り付けてください。それだけで手間が省ける場合があります。あと、ソースに現れていない自作関数(infile_scanfなど)がありますので、これらもソースを開示していただいた方が、解決への近道になると思います。
dodox86

2020/07/27 17:36

ご質問に挙げられているコードのコンパイルですが、gccですと警告だらけです。stdio.hやstdlib.hのincludeは必要ないのでしょうか。また、infile_open関数が無いので、リンクエラーとなり、実行できません。 (infile_open関数を使うための独自の*.hファイルがあり、そのため、stdio.h などのincludeが必要ないのでしょうか) 更に、全角空白文字がありソースコードの文字コードによってはその部分でもエラーになります。 開発環境も明示してください。(Visual Studio、gcc,など)
guest

回答4

0

C

1int main(int argc, char* argv[]) { 2 char* n = NULL; 3 ... 4 infile_scanf("%s", n); /*=scanf*/

infile_scanfとやらが"ファイルを入力源とするscanf"だとすると、
ファイルから文字列を読みだして n に収めてくれるのかな。
ところが n = NULL だから文字列を収める領域がどこにもない。セングメントエラーとなるのも無理はない。

投稿2020/07/27 23:33

episteme

総合スコア16614

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

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

German_p0tat0

2020/07/28 05:22

なるほど、NULLで初期化すると領域も消えるんですね。 私も最初は初期化しなかったんですが、コンパイルすると"初期化せずに使用されてます"と出たのでNULLでしていました。 今、0で初期化してコンパイルして実行したところまた、セグメントエラーでした。(修正版は上の質問の所のコードです)
episteme

2020/07/28 07:14

char* n 改め char n[64] とかではどうですか? # a, b, c についても
German_p0tat0

2020/07/28 09:59

配列じゃなくて、malloc関数での動的メモリを使いたいんですよ。
German_p0tat0

2020/07/28 10:15

質問文に私のやりたい事のイメージ図を載せたのであっているか見てください。
episteme

2020/07/28 11:20

だったら char* n = malloc(テキトーなサイズ); でえぇやん
German_p0tat0

2020/07/28 11:44

なるほど、宣言の時に確保してもいいんですね。
German_p0tat0

2020/07/28 15:40

全て解決しました。ありがとうございました。
guest

0

ベストアンサー

C言語のポインタ変数は、アドレスの場所を格納するだけで、その先の領域がどうなっているかは関知しません。

char *n = 0; とした場合、nにはアドレスとして0が格納されますが、0番地のメモリアドレスの権利を確保する訳ではありません。
infile_scanf("%s", n);
これが、nの指す先にデータを書き込む関数であるとするならば、確保していないアドレス(0番地)に勝手にデータを書き込むので、エラーになって落ちます。
配列等で領域を確保して、そのアドレスをポインタに代入するか、malloc等で動的にデータを書き込む領域を確保して、そのアドレスを渡してください。

そのほか、a,b,c等のポインタ変数も同様です。
ポインタ変数は宣言しただけでは、領域は確保されません。

例えばこんな風にするとか。

C

1// char *n = 0; 2 char n[20]; 3 4// char *a = 0, *b = 0, *c = 0; 5 char a[8], b[205], c[106];

追加?

C

1 while(strcmp(pos,"0") != 0){     /*0が入力されるまで検索を続ける*/ 2 3// 省略 4 5 printf("%d件見つかりました",flag); 6 7 infile_scanf("%s", pos); 8 9 }

この最後のinfile_scanf("%s", pos);は何でしょう?
前半でファイルの読み込みは終わっているはずなのに、これでさらに読み込んでエラーが出る。
そのまま、whileに戻って、posの値は(おそらく)書き換わらないので、whileは回り続けて
無限ループとなり、エラーが出続ける。
のだと思います。

投稿2020/07/28 07:31

編集2020/07/28 12:09
amiya

総合スコア1216

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

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

German_p0tat0

2020/07/28 10:14

質問文に私のやりたい事のイメージ図を載せたのであっているか見てください。
amiya

2020/07/28 10:25

そのイメージ図に到達する以前の問題です。 コードでは、「入力を受ける」→「(図に書かれているような)リストに格納する」という手順ですが、 「入力を受ける」段階でエラーが発生しています。 入力を受け取って、リストのノードに内容をコピーする前の一時的なデータ置き場が確保されていないのです。 char *n = 0; char *a = 0, *b = 0, *c = 0; これらのポインタ群の実体エリアが確保されていないのが問題です。
German_p0tat0

2020/07/28 11:16

私はmallocを使って動的にメモリを確保したかったのですが、その場合は文字列を格納するa,b,cは配列を利用して、をmallocで確保したpが指すアドレスの構造体に入れればよかったのですね。ありがとうございます
amiya

2020/07/28 11:29

nやabcの領域をmallocで確保することもできますが、無駄なだけで特に意味がないかと。 それであれば、始めから、mallocで一つノードを確保しておいて、そのノードの各要素のアドレスに 直接入力してしまうとか。
German_p0tat0

2020/07/28 11:46

それがおっしゃっていただいた配列を使う方法なのですね。参考になります。 それで連結リストに無事格納できました。 でもまた新たにエラーが起きました。
German_p0tat0

2020/07/28 15:37 編集

すみません。コピペをミスりました。次からちゃんと確認して投稿します。
German_p0tat0

2020/07/28 15:39

全て解決しました。ありがとうございました。
guest

0

infile_scanfもstrcpyもどちらもSEGVですね。
→ポインタ変数a,b,cどれもNULLポインタですから。

構造体ポインタpはちゃんとmallocでメモリ割り当てしているのに、なぜa,b,cには
メモリ実体を割り当てていないのでしょうか?

自分ではこれでちゃんと動くと思うのですが

動きませんよ。
配列とポインタをもっと学習しましょう!

投稿2020/07/28 01:57

DreamTheater

総合スコア1095

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

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

German_p0tat0

2020/07/28 05:16

前にメンバがint型の値を1つもつ構造体の動的メモリ確保をしのですが、その時は構造体ポインタpだけをmallocでメモリ割り当てしてint型の値はp->x = y のように代入できたんですよ。なので今回も同じような感じでしたら、 main.c:69:15: エラー: assignment to expression with array type p->no = a; ^ main.c:70:17: エラー: assignment to expression with array type p->addr = b; ^ main.c:71:17: エラー: assignment to expression with array type p->yomi = c; のようなエラーが出て、調べるとstrcpyを使うとエラーが消えるとでたのでstrcpyを使いました。
DreamTheater

2020/07/28 06:28 編集

それはyがintの変数(非ポインタ)だからですよ。 ポインタでない変数なら宣言時にメモリ実体も確保されます。 それとa,b,c宣言時のNULL代入を0代入に修正されていますが、実質同値ですよ。 また、コンパイルエラー(assignment to expression with array type)の回避策をstrcpyとしても、今のままでは実行時エラーとなります。 a,b,cのポインタには正当なメモリアドレスが設定されていないからです。 このコンパイルエラーは配列名(≒ポインタ)に代入しちゃだめですよという意味です。 配列名はその配列のメモリアドレスを指しているだけで器があるわけではありません。 数値の1に10を代入するようなものだと言えばいいのかな。 1 = 10 上記が代入式として適切でないことは理解できますよね?
German_p0tat0

2020/07/28 10:15

なるほど、理解できます。 質問文に私のやりたい事のイメージ図を載せたのであっているか見てください。
German_p0tat0

2020/07/28 15:40

全て解決しました。ありがとうございました。
guest

0

セグメントエラーというのは、どこかでメモリ破壊やアクセス違反が起こっているときに出ます

提示のコードはそのままではコンパイルができません。また、定義がない関数もあるようです。
まずは、こちらでコピペできちんと動作するコードを提示しましょう。

投稿2020/07/27 21:38

y_waiwai

総合スコア87719

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

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

German_p0tat0

2020/07/28 05:26

すみません。includeなどはコピペミスでした。また定義されてない関数はlibrary.hにあり、もともと提供されているものなので、まちがってないだろうと思い、私が内容を簡単に説明するだけにしていました。 必要ならば載せますが、たぶん私のアルゴリズムのどこかが間違っていると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問