【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.22006

fgets
投稿者---黒ぺけじぇー(2005/07/21 10:13:18)


現在、文字列の読み取りなどをするプログラムを作成しているのですが、その読み取りに"fgets"を使用していて、調べてみたところfgetsの1レコードとみなす条件が「改行コードまで、もしくわ、EOFを検出したとき」までとあったのですが、その条件を改行コードまでとしてEOF検出時はまだ1レコードと見なさないようにする方法ありませんか?
win2000 cygwin


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:fgets 22007 まきじ 2005/07/21 10:22:18
<子記事> Re:fgets 22008 KKK 2005/07/21 10:31:52
<子記事> Re:fgets 22009 円零 2005/07/21 10:33:30


No.22007

Re:fgets
投稿者---まきじ(2005/07/21 10:22:18)


>EOF検出時はまだ1レコードと見なさないようにする方法ありませんか?

EOF がくれば End Of File なので、それ以降にレコードはないと思いますが?


この投稿にコメントする

削除パスワード

No.22010

Re:fgets
投稿者---黒ぺけじぇー(2005/07/21 10:40:20)


>EOF がくれば End Of File なので、それ以降にレコードはないと思いますが?

言葉足らずでした。すみません。
文字列の読み込みのプログラム(プログラムA)と同時に文字列の書き込みを行っているプログラム(プログラムB)もありまして、現状だとプログラムBがまだ1レコード書ききっていないのにプログラムAがEOFを検出して途中書きのレコードを1レコードとしてしまって。。。これをなんとかしたいのです。
プログラムBの文字列書き込みの際にfflushを使用するとうまくいくのですが、これをプログラムAのほうでなんとかしたいのです。
良い方法ありませんか?


この投稿にコメントする

削除パスワード

No.22011

Re:fgets
投稿者---まきじ(2005/07/21 10:45:12)


>文字列の読み込みのプログラム(プログラムA)と同時に文字列の書き込みを行っているプログラム(プログラムB)もありまして

マルチスレッドか何かでしょうか?
A で全部読み込んでから、B で書き込んでは駄目なんでしょうか?
取り敢えず、ソースを提示してみてはどうでしょうか?


この投稿にコメントする

削除パスワード

No.22012

Re:fgets
投稿者---黒ぺけじぇー(2005/07/21 11:01:33)


>マルチスレッドか何かでしょうか?
>A で全部読み込んでから、B で書き込んでは駄目なんでしょうか?
>取り敢えず、ソースを提示してみてはどうでしょうか?

上手く説明できなくてごめんなさい。
えっと、「リアル監視モニター」(条件HITしたレコードを抜出してくる)みたいなのを作っています。
本番環境ではプログラムBの文字列(実際は可変長のシステムログ)はシステムダウンさせる時以外は不定期(秒数百件)にはかれるもので、プログラムAもシステムが稼動している間は常に監視をしているというものです。
簡易版ソースを載せておきます。

/*プログラムA*/
#include <stdio.h>
#include <process.h>
#include <string.h>

#define FILENAME_INPUT    "XXXXXXXXXXXXXXXXXXX/input.txt"      //INPUTファイルの名前
#define FILENAME_OUTPUT  "XXXXXXXXXXXXXXXXXXX/output.txt" //OUTPUTファイルの名前
#define FILENAME_END        "XXXXXXXXXXXXXXXXXXX/end.txt"      //ENDファイルの名前

int main(void)
{
    FILE    *fpi;         //INPUTFILEの構造体POINTER
    FILE    *fpo;         //OUTPUTFILEの構造体POINTER
    FILE    *fpx;         //ENDFILEの構造体POINTER
    char    buff1[1024];    //1レコードが入るどんがら
    char    *buff2="go";    //検索文字
    char    *ans;         //検索結果の戻値
    int  z=0;   //ループカウント

    /*----FILEOPEN----*/
    if ((fpi=fopen(FILENAME_INPUT,"r"))==NULL){    //INPUTファイルをオープン
        exit(1);
    }
    fpo=fopen(FILENAME_OUTPUT,"a");       //OUTPUTファイルをオープン
    printf("はじめ\n");

    /*----検索処理----*/
    while(1){                                    //永久ループ開始
        ++z;
        
        if ((fgets(buff1,1024,fpi))!=NULL){     //1レコードをbuff1に入れちゃう
            ans=strstr(buff1,buff2);                        //検索して戻値をansへ
            if (ans!=NULL){         //検索HITした場合の処理
                fputs(buff1,fpo);                     //output.txtに出力
            }
        }
        if (z==100){                                    //100ループ毎に終わらすかどうか判断する
            z=0;
            if ((fpx=fopen(FILENAME_END,"r"))!=NULL){   //終了手段はend.txtを作成する
                break;                  //end.txtがオープンできたら脱出!
            }
        }
    }

    fclose(fpi);
    fclose(fpo);
    fclose(fpx);
    printf("おわり\n");
    return 0;
}


/*プログラムB*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define FILENAME_INPUT    "XXXXXXXXXX/input.txt"    //INPUTファイルの名前

int main(void)
{
    /*----変数定義----*/
    FILE    *fpi;         //INPUTFILEの構造体POINTER
    int  i;            //レコードカウント
    int  j;            //乱文字数カウント変数
    int  x;            //アルファベット26文字どれかの番号をいれる
    int  c;            //決定されたアルファベットをいれる

    /*----FILEOPEN----*/
    fpi=fopen(FILENAME_INPUT,"a");  //INPUTファイルオープン

    /*----乱数系列の変更----*/
    srand((unsigned) time(NULL));

    printf("サクセイチュウアル\n");

    /*----a〜zの文字列をjjjj個ずつiiiii行発生----*/
    for (i=1;i<=1000;i++)         //iレコード生成
    {

        for (j=0;j<999;j++)   //乱文字j個生成
        {
            x=rand()%26;
            c='a'+x;                //ランダム数字をランダムアルファベットにする
            putc(c,fpi);
        }
        fputs("\n",fpi);            //最後に\nを付加して改行
    }
    fclose(fpi);

    printf("オワタアル\n");

    return 0;
}





この投稿にコメントする

削除パスワード

No.22013

Re:fgets
投稿者---まきじ(2005/07/21 11:21:28)


A と B に繋がりがない、A と B がまったく別のプログラムとして
動作してるので、B が書き込む前に、A が読み込むと、
input.txt にレコードが存在しない可能性がある。

input.txt にレコードが存在しない場合は、A は、B が書き込み
をするのを待つ様な処理が必要だと思います。
(同期を取る必要があると思います。)
B が終了していれば、A は input.txt の残りレコードを読み込んで
終了させる。

スレッドなどを使えば、良いと思います。

#詳しくは解りません・・・


この投稿にコメントする

削除パスワード

No.22019

Re:fgets
投稿者---chu-(2005/07/21 13:59:32)


これでどうだろう。

/*プログラムA*/
#include <stdio.h>
#include <process.h>
#include <string.h>

#define FILENAME_INPUT    "XXXXXXXXXXXXXXXXXXX/input.txt"      //INPUTファイルの名前
#define FILENAME_OUTPUT  "XXXXXXXXXXXXXXXXXXX/output.txt" //OUTPUTファイルの名前
#define FILENAME_END        "XXXXXXXXXXXXXXXXXXX/end.txt"      //ENDファイルの名前

int main(void)
{
    FILE    *fpi;         //INPUTFILEの構造体POINTER
    FILE    *fpo;         //OUTPUTFILEの構造体POINTER
    FILE    *fpx;         //ENDFILEの構造体POINTER
    char    buff1[1024];    //1レコードが入るどんがら
    char    *buff2="go";    //検索文字
    char    *ans;         //検索結果の戻値
    int  z=0;   //ループカウント
    char *p;                                                                    /*変更*/
    int c;                                                                      /*変更*/

    /*----FILEOPEN----*/
    if ((fpi=fopen(FILENAME_INPUT,"r"))==NULL){    //INPUTファイルをオープン
        exit(1);
    }
    fpo=fopen(FILENAME_OUTPUT,"a");       //OUTPUTファイルをオープン
    printf("はじめ\n");

    /*----検索処理----*/
    p = buff1;                                                                  /*変更*/
    while(1){                                    //永久ループ開始
        ++z;
        
/*      if ((fgets(buff1,1024,fpi))!=NULL){     //1レコードをbuff1に入れちゃう  /*変更*/
        if ( (c = fgetc(fpi)) != EOF )                                          /*変更*/
            *p++ = c;                                                           /*変更*/
        if ( c == '\n' ) {                                                      /*変更*/
            *p = '\0';                                                          /*変更*/
            p = buff1;                                                          /*変更*/
            ans=strstr(buff1,buff2);                        //検索して戻値をansへ
            if (ans!=NULL){         //検索HITした場合の処理
                fputs(buff1,fpo);                     //output.txtに出力
            }
        }
        if (z==100){                                    //100ループ毎に終わらすかどうか判断する
            z=0;
            if ((fpx=fopen(FILENAME_END,"r"))!=NULL){   //終了手段はend.txtを作成する
                break;                  //end.txtがオープンできたら脱出!
            }
        }
    }

    fclose(fpi);
    fclose(fpo);
    fclose(fpx);
    printf("おわり\n");
    return 0;
}



この投稿にコメントする

削除パスワード

No.22017

Re:fgets
投稿者---nop(2005/07/21 13:20:18)


>文字列の読み込みのプログラム(プログラムA)と同時に文字列の書き込みを行っているプログラム(プログラムB)もありまして、現状だとプログラムBがまだ1レコード書ききっていないのにプログラムAがEOFを検出して途中書きのレコードを1レコードとしてしまって。。。これをなんとかしたいのです。

これは、正しくファイルの排他制御を行うべきです。
そもそも、書込を行っている最中に読み込む事が間違っているのですから、
然るべき排他制御を行う事が解決策になると思います。

監視ソフトであればなおさらです。

# 監視ソフトであれば、半端なレコードは無いものと見なす、
# と言う妥協案もあるかと。
# 次の監視サイクルで再読み出しされる事が条件となりますがね。


この投稿にコメントする

削除パスワード

No.22008

Re:fgets
投稿者---KKK(2005/07/21 10:31:52)


> EOF検出時はまだ1レコードと見なさないようにする方法ありませんか?

最後の1レコードを無視したいということでしょうか?
だとしたら、最後の1レコードを無視するような関数を作成するなどすれば良いと思います。


この投稿にコメントする

削除パスワード

No.22009

Re:fgets
投稿者---円零(2005/07/21 10:33:30)


EOF出てるのに行が終わってないと言うのが一体どういう状況なのかはわかりませんが、
最後の文字を見てそれが改行文字であるかどうかを判別すればいいんじゃないですかね。
つまり、
fgets(string, n, stream);
のように読んだとしたら
if(string[strlen(string) - 1] != '\n') /*何らかの処理*/ ;
みたいにして対処すると。


この投稿にコメントする

削除パスワード

No.22014

Re:fgets
投稿者---あかま(2005/07/21 11:24:30)


もしくはfeof使ってEOFならレコードの整合性チェックするとか。
http://www9.plala.or.jp/sgwr-t/lib/feof.html

レコードを書き出す側はレコード単位で書き出せばあまり起こらないかも。



この投稿にコメントする

削除パスワード

No.22015

Re:fgets
投稿者---黒ぺけじぇー(2005/07/21 12:21:57)


みなさんありがとうございました。
プログラムBの方はあくまでテスト用に作成しただけであって、プログラムBの出力の仕方等を変更させずにプログラムA単独でもきちんと改行コードで1レコードとしたいのです。

あかまさんの
>レコードを書き出す側はレコード単位で書き出せばあまり起こらないかも。
ですが、とりあえず1度やってみたのですが、1レコード単位でもだめでした。

まだみなさんのアドバイスを全てためせれてないのでちょっとやってみます。(まだC言語勉強して間もないのでいろいろ調べないと)

ありがとうございました。(まだ良い案ありましたらお願いします)


この投稿にコメントする

削除パスワード

No.22016

Re:fgets
投稿者---KKK(2005/07/21 13:13:59)


>プログラムBの方はあくまでテスト用に作成しただけであって、
>プログラムBの出力の仕方等を変更させずにプログラムA単独でもきちんと改行コードで1レコードとしたいのです。

察するに、
プログラムBは既にシステムに組込まれていて修正できない。
プログラムAは全く別のプロセスとして動作するため同期などをとることはできない。
ということでしょうか。

思いつく方法としては、
・1レコード読込む前にファイルポインタの位置を記憶しておく。
・1レコード読込んだら、レコードの最後が"\n"でなかったら、ファイルポインタを戻してリトライ
といったとこでしょうか?(試したことないのでできるかどうか知らないけど。。)


この投稿にコメントする

削除パスワード

No.22024

Re:fgets
投稿者---黒ぺけじぇー(2005/07/21 16:13:14)


みなさんいろいろアドバイスありがとうございました。
おかげでうまくいくようになった(と思います)。


以下に訂正したソースを載せておきます。
/*プログラムA*/
#include <stdio.h>
#include <process.h>
#include <string.h>

#define FILENAME_INPUT    "XXXXXXXXXXXXXXX/input.txt"      //INPUTファイルの名前
#define FILENAME_OUTPUT  "XXXXXXXXXXXXXXX/output.txt" //OUTPUTファイルの名前
#define FILENAME_END        "XXXXXXXXXXXXXXX/data/end.txt"    //ENDファイルの名前

int main(void)
{
    FILE    *fpi;         //INPUTFILEの構造体POINTER
    FILE    *fpo;         //OUTPUTFILEの構造体POINTER
    FILE    *fpx;         //ENDFILEの構造体POINTER
    char    buff1[1024];    //1レコードが入るどんがら
    char    *buff2="go";    //検索文字
    char    *ans;         //検索結果の戻値
    int  z=0;   //ループカウント
    char    *p;
    int  c;
    long    int pos;  //現在の位置

    /*----FILEOPEN----*/
    if ((fpi=fopen(FILENAME_INPUT,"r"))==NULL){    //INPUTファイルをオープン
        exit(1);
    }
    fpo=fopen(FILENAME_OUTPUT,"a");       //OUTPUTファイルをオープン
    printf("はじめ\n");
    /*----検索処理----*/
    while(1){                                    //永久ループ開始
        ++z;
        
        pos=ftell(fpi);          //読む前に位置を記憶
        ret:                                                //goto着地地点
        fseek (fpi,pos,SEEK_SET);                     //ファイルポインタの読み出し位置
        if ((fgets(buff1,1024,fpi))!=NULL){     //1レコードをbuff1に入れちゃう
            if ((buff1[strlen(buff1)-1])!='\n')    //改行コードがなかったら
            {
                goto ret;                           //飛べ!!(リトライ)
            }
            ans=strstr(buff1,buff2);                        //検索して戻値をansへ
            if (ans!=NULL){         //検索HITした場合の処理
                fputs(buff1,fpo);                     //output.txtに出力
            }
        }
        if (z==100){                                    //100ループ毎に終わらすかどうか判断する
            z=0;
            if ((fpx=fopen(FILENAME_END,"r"))!=NULL){   //終了手段はend.txtを作成する
                break;                  //end.txtがオープンできたら脱出!
            }
        }
    }

    fclose(fpi);
    fclose(fpo);
    fclose(fpx);
    printf("おわり\n");
    return 0;
}




この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧