C言語関係掲示板

過去ログ

No.335.単語の出現回数を求め、一覧を使用頻度が多い順に出力

[戻る] [ホームページ]

No.2117

単語の出現回数を求め、一覧を使用頻度が多い順に出力
投稿者---たけむー(2002/07/18 15:37:36)


以下の実行例のように、テキストファイル内に存在する単語をすべて抜き出し、使用頻度が多い順にすべて個数も含めて画面表示するプログラムを作成してください。

the  10回
a    8回
this  6回
 以下略



No.2118

間違えました…
投稿者---たけむー(2002/07/18 15:50:05)


上のような問題が出されたんですが、過去ログ読んだんですが
ソートの部分だけが分かりませんでした
構造体習ったばかりでよく分からなくて^^;
誰か教えてもらえませんでしょうか?

関数化したソース
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define     SEPARATOR   " .,\t\r\n"

typedef int     (*COMP )(const void *,const void *);

typedef struct  {
    char    *pWord;
    int     Count;
} WORDINFO,*PWORDINFO;

/* とりあえず単語種類を200とする */
WORDINFO        WordTbl[200];

int     Compare(PWORDINFO ,PWORDINFO );

int     WordSearch(char *FileName)
{
    PWORDINFO   pSearch,pTbl;
    char        *pText,*tk;
    size_t      uSize;
    size_t      TblLen;
    FILE        *fp;

/*** phase 1 テキストをメモリにロード ***/
    fp = fopen(FileName,"r");
    if (!fp)    
        return 0;

    uSize = (size_t )filelength(fileno(fp));
    pText = (char *)calloc(uSize + 1,sizeof(char ));
    if (!pText){
        fclose(fp);
        return 0;
    }
    fread(pText,uSize,1,fp);
    fclose(fp);

/*** phase 2 単語の位置をテーブルに格納する ***/
    tk = strtok(pText,SEPARATOR);
    while(tk){
        pSearch = WordTbl;
        while(pSearch->pWord){
            if (!strcmp(pSearch->pWord,tk))
                break;
            pSearch++;
        }
        pSearch->pWord = tk;
        pSearch->Count++;

        tk = strtok(NULL,SEPARATOR);
    }

/*** phase 3 ソート ***/
    pTbl = WordTbl; while((pTbl++)->pWord);
    TblLen = pTbl - WordTbl - 1;

    qsort(WordTbl,TblLen,sizeof(WORDINFO ),(COMP )Compare);

    pTbl = WordTbl;
    while(pTbl->pWord){
        printf("%s  .....  %d\n",pTbl->pWord,pTbl->Count);
        pTbl++;
    }

    /* 領域pTextは最後まで解放してはならない */
    free(pText);

    return 1;
}

int     Compare(PWORDINFO ptr1,PWORDINFO ptr2)
{
    return strcmp(ptr1->pWord,ptr2->pWord);
}




過去ログ
http://f1.aaa.livedoor.jp/~pointc/log132.html


No.2125

Re:間違えました…
投稿者---かずま(2002/07/18 18:24:37)


> int     Compare(PWORDINFO ptr1,PWORDINFO ptr2)
> {
>     return strcmp(ptr1->pWord,ptr2->pWord);
> }
これでは頻度順ではなく、アルファベット順になるようですが。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct {
    char *word;
    int  count;
} Node;

int get_word(FILE *fp, char *word, int size)
{
    int c, i = 0;

    do {
        if ((c = getc(fp)) == EOF) return 0;
    } while (!isalpha(c));
    --size;
    do {
        if (i < size) word[i++] = tolower(c);
        c = getc(fp);
    } while (isalpha(c));
    word[i] = '\0';
    return 1;
}

int compare(const void *a, const void *b)
{
    Node *p1 = (Node *)a;
    Node *p2 = (Node *)b;
    return p2->count - p1->count;
}

int main()
{
    char word[256];
    Node table[3000];
    int  ntable = 0, i;

    while (get_word(stdin, word, sizeof word)) {
        for (i = 0; i < ntable; i++)
            if (strcmp(table[i].word, word) == 0)
                break;
        if (i == ntable) {
            if (++ntable > sizeof table)
                return fprintf(stderr, "too many words\n"), 1;
            table[i].count = 1;
            table[i].word = strdup(word);
            if (table[i].word == NULL)
                return fprintf(stderr, "out of memory\n"), 1;
        } else
            table[i].count++;
    }
    qsort(table, ntable, sizeof *table, compare);
    for (i = 0; i < ntable; i++)
        printf("%4d %s\n", table[i].count, table[i].word);
    return 0;
}

qsort は標準ライブラリの関数で、その第4引数は比較関数へのポインタです。
その比較関数は、qsort に渡した配列の 2つの要素を指すポインタを受け取り、
比較結果を、負、ゼロ、正の値で返すように書くことになっています。


※書き込み者より訂正があります。(管理人追加)

No.2128

Re:間違えました…
投稿者---たけむー(2002/07/18 23:24:03)


>qsort は標準ライブラリの関数で、その第4引数は比較関数へのポインタです。
>その比較関数は、qsort に渡した配列の 2つの要素を指すポインタを受け取り、
>比較結果を、負、ゼロ、正の値で返すように書くことになっています。

何とか理解できました。
変な質問の仕方でしたがお答え下さりありがとうございます。