ページ 11

cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 10:10
by 新米
1行ごとに1単語(英単語)が書かれたファイル(行数は不定)があり、そのファイルの内容をソートして出力するプログラム(qsortは利用してはいけない)を作ろうとしているのですが
まず、ソートの機能をつけず1単語ずつ格納し表示するプログラムを作ってみたのですが
これをcygwinで実行すると、読み込んだファイルの先頭の1単語だけ表示された後
「a.exeは動作を停止しました
問題が発生したため、プログラムは正しく動作しなくなりました。プログラムは閉じられ、解決策がある場合はwindowsから通知されます。」
と表示され強制終了します。
原因がまったくわからず困っています。
解決策を教えてください。お願いします。
また、正常になったとしてその後、どうやってソート機能を加えたらいいかのアドバイスもしていただけると助かります。
よろしくお願いします。
以下がプログラムとファイル内容です。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

struct LIST {		//リスト構造用構造体
	struct LIST *next;
	struct LIST *back;
		char word[];
			};

struct LIST start;//リストの1番目

int main(void)
{
	start.next=&start;
	start.back=&start;

	FILE *fp;
	fp=stdin;
	
	while(feof(fp)==0){
		
		struct LIST *box;
		struct LIST *next;
		struct LIST *prev;

		box=(struct LIST*)malloc(sizeof(struct LIST));

		fgets(box->word,10,fp);
		
		box->next=&start;
		
		prev=&start;
		
		for(next=start.next;next!=&start;next=next->next){

			prev=next;
                                  }

		prev->next=box;
		box->back=prev;
		
	}
	//表示
	struct LIST *display;

	for(display=start.next;display!=&start;display=display->next){

		printf("%s",display->word);
	
	}

	return 0;
}
ファイルtest.txt
google
apple
knight
dream
erath

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 10:34
by h2so5
29行目でbox->wordに書き込んでいますが、メモリが確保されていません。

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 10:52
by softya(ソフト屋)
GDBを使うと何処で問題が出たか確認できます。
「GDB」
http://www.fireproject.jp/feature/gdb/

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 11:03
by たかぎ
LIST構造体のwordはゼロ長配列ですので、mallocでメモリを割り付ける際に必要な分を加えたサイズを指定しなければなりません。
たとえば、wordに10バイトのサイズを持たせるには、mallocの引数はsizeof(struct LIST) + 10でなければなりません。

それ以前に、単に標準入力から読み込んだ単語をソートするだけであれば、次のようにすれば実現できます。

コード:

#include <stdlib.h>

int main(void)
{
    system("sort");
}
本来であればsortコマンドを直接呼び出すだけでよいのですが、それではプログラミングになりませんので...

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 11:20
by 新米
[quote="たかぎ"]LIST構造体のwordはゼロ長配列ですので、mallocでメモリを割り付ける際に必要な分を加えたサイズを指定しなければなりません。
たとえば、wordに10バイトのサイズを持たせるには、mallocの引数はsizeof(struct LIST) + 10でなければなりません。

mallocの引数をこのとおりにすると正常に動作しました。ありがとうございます。
ただ読み込んだファイルは
google
apple
knight
dream
earth
のはずなんですが、dreamまでしか表示されず、最後のearthは表示されませんでした。
なぜですか?またそれはどのように解決すればいいですか?

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 11:29
by 新米
すいません。表示されてました(汗
皆さんご指摘ありがとうございました。
もしよければソート機能の加え方もアドバイスいただけるとありがたいです。

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 11:50
by 新米
質問ばかりですみません。
双方向リストを逆から表示させるにはどうしたらよいのですか?
(earthから表示されてgoogleへの順)

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 13:10
by box
新米 さんが書きました: 双方向リストを逆から表示させるにはどうしたらよいのですか?
(earthから表示されてgoogleへの順)
リスト構造の最後を覚えておき、backポインターを使って順繰りに戻っていくコードを書いてください。

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月14日(月) 19:51
by 新米
ありがとうございます!

Re: cygwinでプログラムが正常に動作しません。

Posted: 2012年5月15日(火) 02:51
by かずま
元のプログラムで、malloc(sizeof(struct List) + 10); としても
解決していませんよ。
最後の表示を printf("[%s]", display->word); としてみてください。

コード:

[google
][apple
][knight
][dream
][erath
][]
ひとつ余計な [] が最後についています。
これは、feof(fp) の使い方を間違っているから起こるものです。
fgets() で最後の行の "erath\n" を読み込んで EOF に達しても、feof(fp) は
0 のままです。feof(fp) が 0 でなくなるのは、次の fgets() で読み込みに失敗したときです。
ファイルのデータを全部読み終わったかどうかは、fgets() の返却値で判断してください。

次に、start を使って、環状の双方向連結リストを構成しているのだから、
リストの先頭も末尾もすぐに参照できます。
新しく読み込んだデータをリストの末尾に追加するために先頭から順番にたどっていく必要はありません。

ということで、プログラムは、次のようになります

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct LIST {
    struct LIST *next;
    struct LIST *back;
    char word[];
};
 
int main(void)
{
    FILE *fp = stdin;
    struct LIST *box;
    struct LIST start;
    start.next = &start;
    start.back = &start;
 
    while (1) {
        box = (struct LIST *) malloc(sizeof(struct LIST) + 10);
        if (fgets(box->word, 10, fp) == NULL) {
            free(box);
            break;
        }
        box->next = &start;
        box->back = start.back;
        start.back->next = box;
        start.back = box;
    }
    for (box = start.next; box != &start; box = box->next)
        printf("%s", box->word);
    return 0;
}
malloc のエラーチェックと、対応する free は省略しています。
sort もまだ解決していません。