ページ 11

ファイルの読み書き

Posted: 2010年7月28日(水) 11:28
by ひよこん
初歩的な質問で大変申し訳ありません
ファイルをfgetsで読み込んだものをfprintfで書き込む方法を教えてください。

FILE *fp;
FILE *text
char str[100];
char *tt= "10";
char *search;

while(fgets(str,sizeof(str),fp))
{
if(tt != NULL)
{
search = strstr(str,tt);
fprintf(text, "%s", search);
}
}

セグメンテーション違反とのエラーになっているのですが、どのように解決すればいいのでしょうか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 11:32
by シエル
fopenした?ほかにもたくさん変なとこあるけど。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 11:46
by ひよこん
変な所!? どこを直せばいいのでしょう!?

fopenはしました!

if(!(fp = fopen("sample.txt", "r"))){
printf("can not open file.\n");
}

while(fgets(str,sizeof(str),fp))
{
if(tt != NULL)
{
search = strstr(str,tt);
fprintf(text, "%s", search);
}
}
fclose(fp);
fclose(text);

上記のようにしています

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 12:01
by バグ
読み込み用のファイルはオープンされているようですが、書き込み用ファイルはオープンされていないように見えます。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 12:09
by シエル
if(tt != NULL)
↑これは何か意味があるんですか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 12:56
by ひよこん
>読み込み用のファイルはオープンされているようですが、書き込み用ファイルはオープンされていないように見えます。

書き込み用ファイルを追記してみました!
エラーはそのままです。


>if(tt != NULL)
↑これは何か意味があるんですか?

search = strstr(str,tt);
if(tt != NULL)

strstrの検索値で使用しようとしていました。

以下に変更してみましたがセグメンテーション違反がでてしまってしまいました

if(!(fp = fopen("sample.txt", "r"))){
printf("can not open file.\n");
}
if(!(text = fopen("test.txt", "w"))){
printf("can not open file.\n");
}

while(fgets(str,sizeof(str),fp))
{
search = strstr(str,tt);
if(tt != NULL)
{
fprintf(text, "%s", search);
}
}
fclose(fp);
fclose(text);

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:08
by シエル
いえ、ttの値は変化しないのに、なぜif文で判定しているのかと思いまして。。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:09
by Mist
if(tt != NULL)



if(search != NULL)

の間違いじゃないですか?
ttがNULLになることは無いですよ。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:11
by toyo
fopenに失敗してるんじゃないでしょうか
sample.txtのパスが違うとか

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:42
by ひよこん
>fopenに失敗してるんじゃないでしょうか
>sample.txtのパスが違うとか

if(search != NULL || search_20 != NULL)
{
printf("%s", search);
fprintf(text, "%s", search);
  }
printfすると、出力されるのでfopenは成功してると思っていたんですが、できていないのもあるんですか!?
調べてみます
fprintfの使い方を見直します。


> if(search != NULL)
にしてみました。セグメンテーション違反はなくなったのですが

次にもう一つ検索条件を追加しなければいけないのを忘れていまして

char *search_20;
char *tt_20 = "20";

while(fgets(str,sizeof(str),fp))
{
search = strstr(str,tt);
search_20 = strstr(str,tt_20);

if(search != NULL || search_20 != NULL)
{
fprintf(text, "%s", search);
fprintf(text, "%s", search_20);
}
}
上記のようにしたらまた、セグメンテーション違反になってしまいました。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:46
by ぜらーちん
簡単に作ってみた(if~elseの分岐は逆がいいかもしれないけど!になってたからこういう風に)

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

#define BUF 256
#define WORD "10"

int main(){

FILE *fp = NULL;
FILE *text = NULL;
char str[BUF] = {'\0'};
char *tt= WORD;
char *search = NULL;

if(!(fp = fopen("sample.txt", "r"))){
printf("can not open file.\n");
}
else{ //検索ファイルが読み込めたら
if(!(text = fopen("test.txt", "w"))){
printf("can not open file.\n");
}
else{ //出力ファイルも読み込めたら
while(1)
{
if(fgets(str, BUF, fp) == NULL){
break;//最後になるまで取り出し
}

search = strstr(str, tt); //検索してみる
if(search != NULL){ //見つかった
fprintf(text, "%s", search);
}
}
}
}
if(fp != NULL){
fclose(fp); //開いてもいないのに閉じたら困るため
}
if(text != NULL){
fclose(text); //開いてもいないのに閉じたら困るため
}

return(0);
}


エラーが出てた場所はここ
if(tt != NULL)
{
fprintf(text, "%s", search);
}

なんかこの辺で出てたきがする
その辺は調べて(’’

後if文だけど、ttで判定しても意味ない気がする
searchにNULLかアドレスだっけ、が入るのだから
searchで見ないとダメな気がする

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 13:50
by バグ
if(search != NULL || search_20 != NULL) 
   { 
        fprintf(text, "%s", search); 
        fprintf(text, "%s", search_20); 
   }
この判定文はまずいんじゃない?片方がNULLの場合でも書き込みしちゃうけど…?
っていうか、どうしたいの?

ひょっとして、どちらもNULLでない場合に両方書き込みたいの?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:06
by ひよこん
ぜらーちん様ありがとうございます。
サンプルを提示していただきまして、早速なおしてなんでできないのか探してみます

>ひょっとして、どちらもNULLでない場合に両方書き込みたいの?
そうなのです。どちらかでもあれば、ファイルに書き込むという処理を入れたいです。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:08
by ぜらーちん
条件式が複数ある場合()したほうがいいと思う
× if(search != NULL || search_20 != NULL)
○ if( (search != NULL) || (search_20 != NULL) )

後、みたことなかったので質問なのですが

while(fgets(str,sizeof(str),fp))

これでループ条件としてはきちんと成り立っているのでしょうか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:10
by シエル
>そうなのです。どちらかでもあれば、ファイルに書き込むという処理を入れたいです。

ん?どっちかがNULLだった場合に今のままじゃNULLの方も書き込んでしまうと思いますが。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:17
by ぜらーちん
なんか違和感あったと思ったら
while(fgets(str,sizeof(str),fp))

条件式がなかったのか

NULLになるまで回したいなら
while(fgets(str, sizeof(str), fp) != NULL)
じゃないと、ダメなような

if(search != NULL || search_20 != NULL){
fprintf(text, "%s", search);
fprintf(text, "%s", search_20);
}

↑だと、探せてもいない方を書き込もうとしたり
両方探せてたら二回書き込むことになるんじゃない?

//search出来ていた場合
if(search != NULL){
fprintf(text, "%s", search);
}
//search_20出来ていた場合
else if(search_20 != NULL){
fprintf(text, "%s", search_20);
}

で、いいのではないでしょうか?
二回デテキタラ…
else{
if(xxxx){}
}
で・・・

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:18
by ひよこん
>while(fgets(str,sizeof(str),fp))
これでループ条件としてはきちんと成り立っているのでしょうか?

ファイルの中身を最初から最後まで表示されてましたのでいいのかと・・・

>ん?どっちかがNULLだった場合に今のままじゃNULLの方も書き込んでしまうと思いますが。

そうなんです!ファイルに書き込み処理がうまくいってないのであれなんですが
printfなどで表示されるとNULLなのに表示されてしまうんです。
でも、どうしたらでなくなるのかわからないんです。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:25
by バグ
>>ひよこんさん
>>そうなのです。どちらかでもあれば、ファイルに書き込むという処理を入れたいです。

結局どっちなの?(^_^;)
「どちらかでもあれば、ファイルに書き込む」というのは、「NULLではない有効なデータのみを書き込む」という事ですか?


>>ぜらーちんさん
>>条件式が複数ある場合()したほうがいいと思う
>>× if(search != NULL || search_20 != NULL)
>>○ if( (search != NULL) || (search_20 != NULL) )

自分の意図したように動いているならば、これは問題ないと思いますよ?
個人的には今回程度の判定文ならば、上記の方が好きですね。

更に条件が増えてきた場合は縦に並べますが…
if (search    != NULL ||
    search_1  != NULL ||
    search_2  != NULL ||
    search_3  != NULL ||
    search_4  != NULL ||
    search_20 != NULL)
{
    /* なんらかの処理 */
}
こんな感じ?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:30
by ひよこん
>「NULLではない有効なデータのみを書き込む」という事ですか?
そのようにしたいです

strstr()で探して、検索対象文字が見つかったらファイルに保存!
したいのはこれだけなんですが、うまくいかなくて(;;)

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:34
by シエル
検索文字が見つかったら、その行だけファイルに保存したいってことですか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:36
by バグ
おっとすれ違いでしたね。
if (search != NULL)
{
    fprintf(text, "%s", search);
}

if (search_20 != NULL)
{
    fprintf(text, "%s", search_20);
}
そういう事ならこれでどうでしょ?


>>ぜらーちんさん
>>なんか違和感あったと思ったら

>>while(fgets(str,sizeof(str),fp))

>>条件式がなかったのか

>>NULLになるまで回したいなら

>>while(fgets(str, sizeof(str), fp) != NULL)

>>じゃないと、ダメなような

駄目ではないです。
NULLが戻れば条件は必ず「偽」になって抜けるので、結果的にNULLではない値の間はループを続けられます。
勿論、明示的にすることによる読みやすさの向上というメリットはあります。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:40
by ひよこん
そうなのです。それでコレでできないかな?と思ったら動かなくて・・・

char *tt = 10
char *tt_20 = 20 

search = strstr(str,tt);
search_20 = strstr(str,tt);
 if((search != NULL ) || (search_20 != NULL ))
{
fprintf(text, "%s", search);
fprintf(text, "%s", search);
}

strstrで探して、
>検索文字が見つかったら、その行だけファイルに保存したい
そうしたいのです。

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:46
by シエル
どちらの検索文字も見つかったら、その「行」を書き込むんだったら、

if(search!=NULL && search_20!=NULL)
{
fprintf(text,"%s",str);
}

どちらか一つでも、あれば書き込むんだったら

if (search != NULL || search_20!=NULL)
{
fprintf(text, "%s", str);
}



でいいのでは?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 14:48
by ぜらーちん
>>バグさん
ifとかの条件式の書き方とかって結局のところ好みですからね~
whileの部分なるほど、NULL省略してもok何ですね。メモメモ

>> if文だけだと、同じのが二回かかれてしまうような

>>ひよこんさん

例えば、例文として以下の文章があったとして…
in.txt
10 20 30 40 50 60
10 10 10 20
50
EOF

出力結果的にはどう出したいのでしょうか?
今のプログラムのままですと
out.txt
10 20 30 40 50 60
10 10 30 10 20

って出ます

それとも
out.txt
10 20
10 10 10 20

って感じに出したいのでしょうか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 15:06
by ひよこん
例えば、例文として以下の文章があったとして…
in.txt
10 20 30 40 50 60
10 10 10 20
50
EOF

↓↓↓↓
out.txt
10 20 30 40 50 60
10 10 30 10 20

10があったからこの行書き込む
20があったからこの行書き込むです

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 15:10
by バグ
>>検索文字が見つかったら、その行だけファイルに保存したい
>>そうしたいのです。

これで、やっとやりたい事が理解できた(^_^;)


>>ぜらーちんさん
>>if文だけだと、同じのが二回かかれてしまうような

確かにその通りですね。失礼いたしました…m(__)m


#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE        1024
#define LOAD_FILE_PATH    "load.txt"
#define SAVE_FILE_PATH    "save.txt"

int main(void)
{
    const char* pKey1 = "10";            // 比較用文字列その1
    const char* pKey2 = "20";            // 比較用文字列その2
    char szBuf[BUFFER_SIZE] = {0, };    // 1行分の文字列読み込み用バッファ
    FILE* pLoad = NULL;                    // 読み出し用ファイルポインタ
    FILE* pSave = NULL;                    // 書き込み用ファイルポインタ


    // 読み出し用のファイルオープン
    if ((pLoad = fopen(LOAD_FILE_PATH, "r")) == NULL)
    {
        // ファイルオープンに失敗
        printf("Load File Open Error\n");
        return -1;
    }

    // 書き込み用のファイルオープン
    if ((pSave = fopen(SAVE_FILE_PATH, "w")) == NULL)
    {
        // 読み出し用のファイルをクローズする
        if (pLoad != NULL)
        {
            fclose(pLoad);
        }

        // ファイルオープンに失敗
        printf("Save File Open Error\n");
        return -1;
    }

    // ファイルの終端まで1行ずつ読み込む
    while (fgets(szBuf, BUFFER_SIZE, pLoad) != NULL)
    {
        // 読み込んだ文字列にキー文字列が存在するか?
        if (strstr(szBuf, pKey1) != NULL || strstr(szBuf, pKey2) != NULL)
        {
            // 文字列が見つかったので書き込む
            fputs(szBuf, pSave);
        }
    }


    // ファイルをクローズして後始末をする
    fclose(pLoad);
    fclose(pSave);
    return 0;
}

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 15:11
by ぜらーちん
なるほど、ちなみに例文修正(30抜けてた)

10 20 30 40 50 60
10 10 30 10 20

後は、10と20が二つあるから
10 20 30 40 50 60
10 20 30 40 50 60

っていう風にもしなくてok何ですよね?
10もしくは20もしくは10と20両方ある行を1行出すみたいな

それでしたら、上に出ているので大丈夫ではないでしょうか?

Re:ファイルの読み書き

Posted: 2010年7月28日(水) 15:21
by ひよこん
ありがとうございます! 動きました!
そして、すっごく勉強になりました。

お手数をお掛けし申し訳ありませんでしたが本当にありがとうございます