C言語関係掲示板

過去ログ

No.500.ファイルの内容をキーワード毎にカウント

[戻る] [ホームページ]
No.5247

ファイルの内容をキーワード毎にカウント
投稿者---長一(2003/02/18 10:48:31)



以下のファイルの内容をキーワード毎にそのレコード数をカウントし、
キーワード毎にその合計を出力します。レコードがない場合は、0件とします。
キーワードを判断し、改行コードをそのキーワードの終わりと判断し、読み込んだ
内容をカウントしたいのですがよい案が浮かびません。
また、キーワードがないときは、無条件で、0件とし、ファイルの最終は、半角スペース
かデータ行です。
よろしくお願いします。

Aファイル
---A処理実行結果 LOG---

-------------------------------
----- A 登録データ -----
-------------------------------
000001,Yamada Taro,A0001
000002,Yamada Hanako,A0001
A00001,Yamada Jiro,A0001

----------------
-- 変更データ --
----------------
A00002,Sato Kouji,B0001
A00003,Katou Kouji,C001
000003,Yamamoto Kouji,A001

----------------
-- 削除データ --
----------------

出力結果は、
登録,変更,削除
A処理:3件,3件,0件

Bファイル
B処理実行結果

---------------------------------
---- B処理 登録ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:47:31] 登録ユーザ 番号:1000
[Thu Feb 13 17:47:31] 登録ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 登録ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31] ----------------------------------------------------
[Thu Feb 13 17:47:50] 登録ユーザ 番号:1002
[Thu Feb 13 17:47:50] 登録ユーザ 情報A:aaa,情報B:bbb,情報C:ccc
[Thu Feb 13 17:47:50] 登録ユーザ 情報D:ddd,情報E:eee,情報F:fff

---------------------------------
---- B処理 変更ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:50:00] 変更ユーザ 番号:0001
[Thu Feb 13 17:47:35] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:47:35] 変更ユーザ 旧情報 情報D,情報E,情報F,
[Thu Feb 13 17:50:00] 変更ユーザ 旧情報 情報G,情報H,情報I,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報D,情報E,情報F,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報G,情報H,情報I,
[Thu Feb 13 17:50:00] ----------------------------------------------------
[Thu Feb 13 17:50:10] 変更ユーザ 番号:0112
[Thu Feb 13 17:50:10] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] 変更ユーザ 旧情報 情報D,情報E,情報F,
[Thu Feb 13 17:50:10] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] 変更ユーザ 新情報 情報D,情報E,情報F,
[Thu Feb 13 17:50:10] ----------------------------------------------------

---------------------------------
---- B処理 削除ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:51:01] 削除ユーザ 番号:2002
[Thu Feb 13 17:51:01] 削除ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:51:01] 削除ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:51:01] ----------------------------------------------------
[Thu Feb 13 17:51:10] 削除ユーザ 番号:2011
[Thu Feb 13 17:51:10] 削除ユーザ 情報A:aaa,情報B:bbb,情報C:ccc
[Thu Feb 13 17:51:10] 削除ユーザ 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:51:10] ----------------------------------------------------
[Thu Feb 13 17:51:12] 削除ユーザ 番号:1015
[Thu Feb 13 17:51:12] 削除ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:51:12] 削除ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:51:12] ----------------------------------------------------


出力結果は、
登録,変更,削除
A処理:2件,2件,3件

Bファイルの場合は、1行で1件ではなく数行で1件としたいのです。
また、その行数は、1行であったり2、3行であったりします。
(複数行で1件とカウントします。変更データの場合は、旧と新併せて1件です。)


No.5254

Re:ファイルの内容をキーワード毎にカウント
投稿者---かずま(2003/02/18 14:47:37)


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

int main(void)
{
    char buf[1024];  int n[4] = { 0 }, i = 0;

    while (fgets(buf, sizeof buf, stdin))
        if (strstr(buf, "登録データ")) i = 1;
        else if (strstr(buf, "変更データ")) i = 2;
        else if (strstr(buf, "削除データ")) i = 3;
        else if (isalnum(*buf & 0xFF)) n[i]++;
    printf("登録,変更,削除\nA処理: %d件, %d件, %d件\n", n[1], n[2], n[3]);
    return 0;
}

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

int main(void)
{
    char buf[1024];  int n[3] = { 0 };

    while (fgets(buf, sizeof buf, stdin))
        if (strstr(buf, "登録ユーザ 番号")) n[0]++;
        else if (strstr(buf, "変更ユーザ 番号")) n[1]++;
        else if (strstr(buf, "削除ユーザ 番号")) n[2]++;
    printf("登録,変更,削除\nB処理: %d件, %d件, %d件\n", n[0], n[1], n[2]);
    return 0;
}


No.5261

isalnum とは
投稿者---むちさん(2003/02/19 11:33:48)


isalnum(*buf & 0xFF))
とは何をしているのでしょうか。?

0xFF=255を演算していると思うのですが、
これで、何が得られるのですか。?

No.5274

Re:isalnum とは
投稿者---かずま(2003/02/19 20:45:45)


> isalnum(*buf & 0xFF))
> とは何をしているのでしょうか。?

読み込んだ行の先頭の 1文字が英数字かどうかをチェックしています。
Aファイルの各行の先頭の 1文字を見てみると、-、改行、0、A だけです。
このうち、レコードとしてカウントするのは 0 と A で始まる行ですから、
そういうチェックをするようにしました。


> 0xFF=255を演算していると思うのですが、
> これで、何が得られるのですか。?

isalnum(c) の c は int型ですが、int の値なら何でもよいのではなく、
unsigned char で表現できる値、または EOF と規格で規定されています。
すなわち、多くの処理系では、-1〜255 の値しか isalnum に渡しては
いけないのです。

ところが、*buf は char型で、これは多くの処理系で -128〜127 の値を持ち
ます。-128〜-1 を 128〜255 に変換するために & 0xFF を実行しています。

isalnum((unsigned char)*buf) と書いてもかまいません。

No.5262

再度お願いします。
投稿者---長一(2003/02/19 12:10:06)


ファイル中にある見出し(処理名)を最後に出力するカウントの行に
つけたいのですが、上手くいきません。
要は、ファイルの最初にある、「----Aプログラム 登録処理 LOG ----」の
Aプログラムを出力結果のカウントの前に「Aプログラム:3件,3件,0件」と
したいのです。

while処理の前に、タイトルを取得するためのwhile処理をつくり、
取得したらbreakで抜けて次のwhile処理に入るように考えたのですが
「Aプログラム」が上手く読めなかったり、読めたりするとカウントの
処理が出来なかったりします。

Aファイル
header1:
header2:

----Aプログラム 登録処理 LOG ----

-------------------------------
----- A 登録データ -----
-------------------------------
000001,Yamada Taro,A0001
000002,Yamada Hanako,A0001
A00001,Yamada Jiro,A0001

出力結果は、
登録,変更,削除
Aプログラム:3件,3件,0件

Bファイルについてですが、カウントの仕方がすこと変わり、
登録、削除、変更に、「注意!!注意!!注意!!」にあったらカウントせず、
別カウントとして出力します。カウントした件数の後に(?件)としたい
のです。
また、登録ユーザと削除ユーザという文字が両方でている個所があり、
その場合は、纏めて1とカウントして別枠で出力したいのですが。

Bファイル
---------------------------------
---- A処理 登録ユーザ一覧 ----
---------------------------------

---------------------------------
---- B処理 変更ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:50:00] 変更ユーザ 番号:0001
[Thu Feb 13 17:47:35] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] ----------------------------------------------------
[Thu Feb 13 17:50:10] 注意!!注意!!注意!!
[Thu Feb 13 17:50:10] 変更ユーザ 番号:0112
[Thu Feb 13 17:50:10] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] ----------------------------------------------------

-------------------------------------------------
---- A処理 から B処理 への変更ユーザ一覧 ----
------------------------------------------------
[Thu Feb 13 17:47:31] 削除ユーザ 番号:1111
[Thu Feb 13 17:47:31] 削除ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 削除ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31]
[Thu Feb 13 17:47:31] 登録ユーザ 番号:1111
[Thu Feb 13 17:47:31] 登録ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 登録ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31] ----------------------------------------------------

出力結果は、
登録,変更,削除
A処理:3件(0件),0件(0件),3件(1件)
B処理:2件(0件),1件(1件),3件(0件)
A処理->B処理:
B処理->A処理:


No.5273

Re:ファイルの内容をキーワード毎にカウント(質問)
投稿者---長一(2003/02/19 19:22:04)


ファイル中にある見出し(処理名)を最後に出力するカウントの行に
つけたいのですが、上手くいきません。
要は、ファイルの最初にある、「----Aプログラム 登録処理 LOG ----」の
Aプログラムを出力結果のカウントの前に「Aプログラム:3件,3件,0件」と
したいのです。

while処理の前に、タイトルを取得するためのwhile処理をつくり、
取得したらbreakで抜けて次のwhile処理に入るように考えたのですが
「Aプログラム」が上手く読めなかったり、読めたりするとカウントの
処理が出来なかったりします。

Aファイル
header1:
header2:

----Aプログラム 登録処理 LOG ----

-------------------------------
----- A 登録データ -----
-------------------------------
000001,Yamada Taro,A0001
000002,Yamada Hanako,A0001
A00001,Yamada Jiro,A0001

出力結果は、
登録,変更,削除
Aプログラム:3件,3件,0件

Bファイルについてですが、カウントの仕方がすこと変わり、
登録、削除、変更に、「注意!!注意!!注意!!」にあったらカウントせず、
別カウントとして出力します。カウントした件数の後に(?件)としたい
のです。
また、登録ユーザと削除ユーザという文字が両方でている個所があり、
その場合は、纏めて1とカウントして別枠で出力したいのですが。

Bファイル
---------------------------------
---- A処理 登録ユーザ一覧 ----
---------------------------------

---------------------------------
---- B処理 変更ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:50:00] 変更ユーザ 番号:0001
[Thu Feb 13 17:47:35] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] ----------------------------------------------------
[Thu Feb 13 17:50:10] 注意!!注意!!注意!!
[Thu Feb 13 17:50:10] 変更ユーザ 番号:0112
[Thu Feb 13 17:50:10] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] ----------------------------------------------------

-------------------------------------------------
---- A処理 から B処理 への変更ユーザ一覧 ----
------------------------------------------------
[Thu Feb 13 17:47:31] 削除ユーザ 番号:1111
[Thu Feb 13 17:47:31] 削除ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 削除ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31]
[Thu Feb 13 17:47:31] 登録ユーザ 番号:1111
[Thu Feb 13 17:47:31] 登録ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 登録ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31] ----------------------------------------------------

出力結果は、
登録,変更,削除
A処理:3件(0件),0件(0件),3件(1件)
B処理:2件(0件),1件(1件),3件(0件)
A処理->B処理:
B処理->A処理:


No.5275

同じこと二度も書き込んでいますが。
投稿者---通りすがり(2003/02/20 00:05:21)


同じことを二度も書き込んでいますが、
出来ないで苦労しているのも分かります。自分にも経験があります。

かずまさんがある程度は参考になるコードをレスしてくれたのです
から、ちょっと考えればできるのではないですか。

それでも、出来なければ質問すればよいと思いますが。



No.5277

いろいろ考えてみたのですが。
投稿者---長一(2003/02/20 09:55:18)



考えてみだのですが、よい案が浮かびませんでした。
お願いします。


No.5282

Re:いろいろ考えてみたのですが。
投稿者---すがり(2003/02/20 13:36:00)


そのいろいろ考えたことを表明してみては?
こう考えたんだけど、ここからわからないって

No.5295

Re:ファイルの内容をキーワード毎にカウント(質問)「Aファイルの処理」
投稿者---柊(2003/02/20 20:40:20)


>要は、ファイルの最初にある、「----Aプログラム 登録処理 LOG ----」の
>Aプログラムを出力結果のカウントの前に「Aプログラム:3件,3件,0件」と
>したいのです。

while (fgets(buf, sizeof buf, stdin)) {
if (sscanf(buf,"----%s* ",title) == 1)
break ;
}
}

>また、タイトルの長さ分、「登録,変更,削除」の前に半角スペースを
>入れたいのですが。

sprintf(edit_fmt,"%%%ds",strlen(title)+2) ;
sprintf(edit_title,edit_fmt,"登録,変更,削除) ;

という風になります。

Bファイルの処理については、別途ね。



No.5315

間違っていました。
投稿者---柊(2003/02/21 10:03:40)


間違ってました。

>sprintf(edit_fmt,"%%%ds",strlen(title)+2) ;
>sprintf(edit_title,edit_fmt,"登録,変更,削除) ;

これだと、スペースが入りませね。
タイトルの長さのフィールドに右詰で出力でする際、たりない
分をスペースで補うわけですから、「登録,変更,削除」が一緒
だったり、長かったりするとスペースが入りません。

要は、タイトル分数右側に移動したいと言うことですよね。
掛け2が必要になります。

sprintf(fmt,"%%%ds",(strlen(title)+2)*2) ;
sprintf(str,fmt,"登録,変更,削除") ;


No.5316

掛け2?
投稿者---通りすがり(2003/02/21 10:20:03)


掛け2?

本当に、掛け2?
タイトルの長さ分移動させたいのでしょ。
それだったらフィールドは、
タイトルの長さ+「: 」の長さ+「登録,変更,削除」の長さ
になるのじゃない。


No.5317

Re:再度の質問。ファイルの内容をキーワード毎にカウント
投稿者---長一(2003/02/21 10:44:45)




Bファイルについてですが、カウントの仕方がすこと変わり、
登録、削除、変更に、「注意!!注意!!注意!!」にあったらカウントせず、
別カウントとして出力します。カウントした件数の後に(?件)としたい
のです。
また、登録ユーザと削除ユーザという文字が両方でている個所があり、
その場合は、纏めて1とカウントして別枠で出力したいのですが。

Bファイル
---------------------------------
---- A処理 登録ユーザ一覧 ----
---------------------------------

---------------------------------
---- A処理 変更ユーザ一覧 ----
---------------------------------

---------------------------------
---- A処理 削除ユーザ一覧 ----
---------------------------------

---------------------------------
---- B処理 登録ユーザ一覧 ----
---------------------------------

---------------------------------
---- B処理 変更ユーザ一覧 ----
---------------------------------
[Thu Feb 13 17:50:00] 変更ユーザ 番号:0001
[Thu Feb 13 17:47:35] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:00] ----------------------------------------------------
[Thu Feb 13 17:50:10] 注意!!注意!!注意!!
[Thu Feb 13 17:50:10] 変更ユーザ 番号:0112
[Thu Feb 13 17:50:10] 変更ユーザ 旧情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] 変更ユーザ 新情報 情報A,情報B,情報C,
[Thu Feb 13 17:50:10] ----------------------------------------------------

---------------------------------
---- A処理 削除ユーザ一覧 ----
---------------------------------

-------------------------------------------------
---- A処理 から B処理 への変更ユーザ一覧 ----
------------------------------------------------
[Thu Feb 13 17:47:31] 削除ユーザ 番号:1111
[Thu Feb 13 17:47:31] 削除ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 削除ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31]
[Thu Feb 13 17:47:31] 登録ユーザ 番号:1111
[Thu Feb 13 17:47:31] 登録ユーザ 登録情報 情報D:ddd,情報E:eee,情報F:fff
[Thu Feb 13 17:47:31] 登録ユーザ 情報G:ggg,情報H:ggg,情報I:iii
[Thu Feb 13 17:47:31] ----------------------------------------------------

出力結果は、
登録,変更,削除
A処理: 3件(0件),0件(0件),3件(1件)
B処理: 2件(0件),1件(1件),3件(0件)
A処理->B処理:
B処理->A処理:



No.5336

この様な処理の流れになるのかな?
投稿者---柊(2003/02/22 10:48:59)


考え方というか、処理の流れは、以下の様になると思いますが。(私個人)

出力結果が、処理後に求めているみたいなので、sscanfを使用して、
「---- A処理 登録ユーザ一覧 ----」がでてきたら、カウントを行う。
つまり、かずまさんが書き込みをしてくれた処理を行えばよいと思います。

1.「---- A処理 登録ユーザ一覧 ----」がでてくるまで読み込みを繰り返す。
2.sscanfを使用して"A処理"という文字列を取り出す。
3.カウントを行うため読み込み処理を行う。
  各ブロックの終わりが改行かスペースか分かりませんが、それがでてくるまで。
4.処理名が前回読み込んだものと同じか判断する。
  違う場合は、出力して、変数を初期化する。
  同じ場合は、処理を継続する。
4."注意"と比較する。
  "注意"があったらカウントする。
5."登録ユーザ 番号"と比較する。
  "登録ユーザ 番号"があったらカウントする。
6.変更ユーザ、削除ユーザに対しても同様の処理を行う。

「A処理 から B処理」と「A処理」を取り出すときのsscanfのフォーマットは
異なるから注意してね。

私も人にアドバイスできるようなスキルを持ち合わせていないので、間違っていたら
ごめんなさい。

では、がんばってください。


No.5406

このようになりました。
投稿者---長一(2003/02/27 15:06:43)


申し訳ありません。
いろいろと親切に教えていただきながらお礼もせずに
申し訳ありません。
一応、動くものができましたが、なんだか長いソースに
なってしまいました。


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

main()
{
    char buf[1024];
    char str[64];
    char title[64];
    char w_title[64];
    char fmt[10];
    char header[64];
    char *p;
    int n[4] = { 0 };
    int m[4] = { 0 };
    int i = 0;
    int j = 0;
    int flg = 0;
    int f_tyuui = 0;

    while (fgets(buf,sizeof buf,stdin)) {
        memset(title,'\0',sizeof title) ;
        if (sscanf(buf,"---- %[^-]s", str) == 1) {
            if (str[0] >= 0x30 && str[0] <= 0x39) {
                continue;
            }
            if (i > 5) {
                p=strtok(str," ");
                strcat(title,p);
                for(j=0; j<2; j++) {
                    p=strtok(0," ");
                    strcat(title," ");
                    strcat(title,p);
                }
            } else {
                sscanf(str,"%s",title);
            }

            if (strncmp(w_title,title,strlen(title)) != 0 && flg == 1) {
                printf("登録,変更,削除\n%s: %d件(%d), %d件(%d), %d件(%d)\n",w_title,n[0],m[0],n[1],m[1],n[2],m[2]);
                n[0] = n[1] = n[2] = n[3] = 0;
                m[0] = m[1] = m[2] = m[3] = 0;
            }

            while(fgets(buf,sizeof buf,stdin)) {
                if (buf[0] == 0x0A) {
                    break;
                }

                if (strstr(buf, "注意"))  f_tyuui = 1;

                if (strstr(buf, "登録ユーザ 番号")) {
                    if (f_tyuui == 1) m[0]++;
                    else n[0]++;
                    f_tyuui = 0;
                } else if (strstr(buf, "変更ユーザ 番号")) {
                    if (f_tyuui == 1) m[1]++;
                    else n[1]++;
                    f_tyuui = 0;
                } else if (strstr(buf, "削除ユーザ 番号")) {
                    if (f_tyuui == 1) m[2]++;
                    else n[2]++;
                    f_tyuui = 0;
                }
            }
            strncpy(w_title,title,strlen(title));
            flg = 1;
            i++;
        }
    }

    printf("登録,変更,削除\n%s: %d件(%d), %d件(%d), %d件(%d)\n",title,n[0],m[0],n[1],m[1],n[2],m[2]);
}


No.5409

Re:このようになりました。
投稿者---通りすがり(2003/02/27 19:40:24)


「A処理からB処理」の個所で、登録ユーザと削除ユーザという文字が両方
でている個所があり、その場合は、纏めて1とカウントして別枠で出力し
たいのですがってところできてませんね。

まだまだですよ。