ページ 11

テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 19:58
by サイクロン
テキストファイルの読み込みが出来なくて困っています。
このプログラムはテキストファイルを読み込んで表示するだけのプログラムです。
すべてmain関数に書いていたときはちゃんと動いていたのですが、
関数に分けたら何故か動かなくなってしまいました。

コード:

 
#include <stdio.h>
#define NUM 40

void readf(char**);

int i,f;

int main()
{
	char* genso[NUM];
	readf(genso);
	for(i=0;i<NUM;i++){
        printf("%s\n",genso[i]);
	}
	return 0;
}	
void readf(char** genso)
{
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	while(1){
		fgets(genso[i],NUM,fp);
		if(feof(fp))break;
  	}
	fclose(fp);
	return;
}
コンパイルはできるのですが、
"Segmentation fault (コアダンプ)"
と表示されて処理が止まってしまいます。
OSはUbuntu13.04でコンパイラはgccです。
どこが間違っているか教えてください。
よろしくおねがいします。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 20:16
by softya(ソフト屋)
このコードだと元から動いていないのでは無いかと思うのですが。
char* genso[NUM];だとchar *をNUM個定義しているだけなので、ポインタの値が未初期化です。
つまり、そのポインタ値を使う以上はSegmentation fault は必然だと思われます。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:03
by サイクロン

コード:

#include <stdio.h>
#define NUM 40

void readf(char**);

int i,f;

int main()
{
	char genso[NUM];
	char** gensop;
	gensop=&genso;
	readf(gensop);
	for(i=0;i<NUM;i++){
		printf("%s\n",&genso[i]);
	}
	return 0;
}
void readf(char** genso)
{
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		i++;
		fgets(genso[i],NUM,fp);
		if(feof(fp))break;
	}
	printf("%d\n",i);
	fclose(fp);
	return;
}
アドバイスどうりにプログラムを変えてみましたが
また別のエラーが出てしまいました。
"genso.c:12:8: 警告: 互換性のないポインタ型からの代入です [デフォルトで有効]"
配列の変数名だけ書くと
配列の最初のポインタが得られるものだと思っていたのですが
何故かエラーが出てしまいます。
どのようにすればエラーが出なくなるでしょうか?

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:14
by non
これは、課題ですか?
課題なら正確に課題を書いてください。
要するに、動的にメモリを確保しなさいという課題なのかわかりません。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:19
by box
サイクロン さんが書きました: すべてmain関数に書いていたときはちゃんと動いていた
では、そのコードを提示してください。
サイクロン さんが書きました: 関数に分けたら何故か動かなくなってしまいました。
なぜだかわからないけど動かない、ということは、まあないでしょうね。
現象には必ず理由があります。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:20
by softya(ソフト屋)
想定されているのは、文字列をNUM個の配列に読み込むことではないのでしょうか?
であれば、まずNUM個分の文字列を用意しないといけません。
文字列は文字の配列ですので、文字の配列をNUM個用意すると言うことです。
現状は、char genso[NUM];ですので、NUM個分の文字の配列が有るだけです。【誤字修正】

nonさんの言われている通り課題であれば、問題の詳細をお願いします。
動いていたという関数を分ける前のプログラムも見せてもらったほうが良いかもしれません。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:34
by サイクロン
動いていたプログラムはこんなかんじです。

コード:

#include <stdio.h>
#define NUM 40

int i,f;

int main()
{
	char genso[NUM];
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	while(1){
		fgets(genso,NUM,fp);
		if(feof(fp))break;
		printf("%s",genso);
	}
	fclose(fp);
	return 0;
}
これは課題などではなく、趣味でやっていることです。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:38
by softya(ソフト屋)
それだと、すでに元のプログラムと想定している動作が変わっています。
そこで質問です。
新しい関数化プログラムでのNUMと元のNUMでは意味は変わっているのでしょうか?
それとも文字列の最大長の意味のままですか?

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:49
by サイクロン
一応同じつもりで書いています。
ただ、僕は初心者なので別の意味になっているかもしれません。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 21:54
by softya(ソフト屋)
サイクロン さんが書きました:一応同じつもりで書いています。
ただ、僕は初心者なので別の意味になっているかもしれません。
であれば、引数にするときにポインタの扱いを間違っていますし、呼び出し元でも全然違う意味で使っています。
まず元のmainだけのプログラムで、入力のwhileループと出力のprintfループを別のループに分離してみてください。
関数化の前に、それが出来ていないと関数化ができません。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:16
by サイクロン

コード:



#include <stdio.h>
#define NUM 40

int i,f;

int main()
{
	char genso[NUM][100];
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		fgets(genso[i],NUM,fp);
		i++;
		if(feof(fp))break;
	}
#if 1
	for(i=0;i<NUM;i++)
	{
		printf("%s",genso[i]);
	}
#endif
	fclose(fp);
	return 0;
}
できました。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:19
by softya(ソフト屋)
NUMの意味が変わっていますが意識してされたことですか?
ちなみに、このプログラムだと何文字の文字列まで正常に動作するかわかりますか。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:21
by サイクロン
NUMの意味が変わったのは意識してやっています。
100文字超えたらアウトだと思います。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:23
by non
15行目 fgets(genso,NUM,fp);
ここ、NUMでいいですか?

20行目 for(i=0;i<NUM;i++)
ここもNUMでいいですか?

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:27
by softya(ソフト屋)
サイクロン さんが書きました:NUMの意味が変わったのは意識してやっています。
100文字超えたらアウトだと思います。
nonさんの指摘のとおりです。
あと100もdefineを希望します。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:36
by サイクロン

コード:

#include <stdio.h>
#define LINE 40                    //文字列の数
#define NUM 100                  //文字列の文字数

int i,f;

int main()
{
	char genso[LINE][NUM];
	char *tmp;
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		fgets(genso[i],sizeof(genso),fp);
		i++;
		if(feof(fp))break;
	}
#if 1
	for(i=0;i<LINE;i++)
	{
		printf("%s",genso[i]);
	}
#endif
	fclose(fp);
	return 0;
}

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:37
by サイクロン
やってみました。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:40
by non
sizeof(genso)
って、具体的にいくつでしょうか?

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:43
by softya(ソフト屋)
for(i=0;i<LINE;i++)
は固定値だとバグになります。
入力していない要素を表示してはいけません。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:52
by サイクロン

コード:

#include <stdio.h>
#define LINE 40
#define NUM 100

int i,flag;

int main()
{
	char genso[LINE][NUM];
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		fgets(genso[i],NUM,fp);
		if(feof(fp))break;
		i++;
	}
	flag=i;
#if 1
	for(i=0;i<flag;i++)
	{
		printf("%s",genso[i]);
	}
#endif
	fclose(fp);
	return 0;
}
できました。
よく考えるとsizeof(genso)は40*100になるんですかね。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 22:55
by non
int i,flag;
はローカル変数にしましょう。

で、どの部分を関数にしたいですか?

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 23:00
by サイクロン

コード:

FILE *fp;
fp=fopen("genso.txt","r");	//ファイルの読み込み
i=0;
while(1){
	fgets(genso[i],sizeof(genso),fp);
	if(feof(fp))break;
	i++;
}
この、ファイルの読み込み部分です。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 23:22
by softya(ソフト屋)
flagは意味不明なので、もっと具体名が良いですね。

で、分離ですがchar genso[LINE][NUM];の引数化と戻り値を考えなくては行けません。
まず、関数プロトタイプだけ書いてみてください。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 23:40
by サイクロン
文字列のポインタを送るだけでいいと思うので、

コード:


#include <stdio.h>
#define LINE 40
#define NUM 100

int readf(char* gensop);    //プロトタイプ宣言
int main()
{
	int i,genso_count;
	char genso[LINE][NUM];
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		fgets(genso[i],NUM,fp);
		if(feof(fp))break;
		i++;
	}
	genso_count=i;
#if 1
	for(i=0;i<genso_count;i++)
	{
		printf("%s",genso[i]);
	}
#endif
	fclose(fp);
	return 0;
}
これで戻り値でgenso_countを返すつもりです。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 23:52
by softya(ソフト屋)
問題は、char* gensopですね。文字列のポインタを送るだけだと1つの行しか読めません。
char* gensopとchar genso[LINE][NUM];は対応する型ではありません。
char *gensopと対応する型はchar genso[NUM];です。
それと前のchar **でも違います。この場合はchar*のポインタ型ですのでchar genso[LINE][NUM];では型が一致しません。
と言うことで、char genso[LINE][NUM];の2次元配列を引数にする場合の対応する型を調べてみてください。正解は2種類あります。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月15日(土) 23:53
by box
サイクロン さんが書きました:

コード:

	char genso[LINE][NUM];
ここが、仮に

コード:

	char genso[LINE];
とか

コード:

	char genso[NUM];
とかだったら、そのプロトタイプ宣言でいいと思います。
ということは、今のプロトタイプ宣言は正しくない、ということです。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月16日(日) 00:10
by サイクロン

コード:

#include <stdio.h>
#define LINE 40
#define NUM 100

int readf(char genso[LINE][NUM])
{
	int i;
	FILE *fp;
	fp=fopen("genso.txt","r");	//ファイルの読み込み
	i=0;
	while(1){
		fgets(genso[i],NUM,fp);
		if(feof(fp))break;
		i++;
	}
	fclose(fp);
	return i;
}
int main()
{
	int i,genso_count;
	char genso[LINE][NUM];

	genso_count=readf(genso);
	for(i=0;i<genso_count;i++)
	{
		printf("%s",genso[i]);
	}
	return 0;
}
無事関数を分けて実行することができました。
ソフト屋さん、nonさん、ありがとうございました。

Re: テキストファイルの読み込みが出来なくて困っています。

Posted: 2013年6月16日(日) 06:19
by non
>int readf(char genso[LINE][NUM])
前の要素数は省略して
int readf(char genso[][NUM])
と書くのが一般的です。関数にはLINEの要素数は渡されませんので。

softya(ソフト屋) さんが書きました:と言うことで、char genso[LINE][NUM];の2次元配列を引数にする場合の対応する型を調べてみてください。正解は2種類あります。
勉強ですから、もう一つの方法を調べてみることをお勧めします。