ショッピングモール  CD/DVD搭載コンポ  CD+HDDコンポ  クラシック調オーディオ  CD/MDシステム


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

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

 詳しくはこちら



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

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


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

No.3309

qsort()を使い、頻出頻度順に表示させたい
投稿者---yos(2005/01/17 16:23:39)


初めまして。
テキストファイルを読み込み、区切った単語を頻度順に表示するプログラムを
作成しています。
単語を区切り、頻度を表示させる所までできました。

後はqsort()を使い、頻出頻度順に表示させたいのですがポインタの理解に苦しみます。
どなたかプログラムの追加をお願いいたします。 

OSはwindows XP 、コンパイラはVC++ です。

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

#define WORD_MAX 100000 /* 単語帳の登録数 */
#define WORD_SIZE 100 /* 単語の最大長 */
char *word[WORD_MAX]; /* 単語帳 */
int freq[WORD_MAX]; /* 頻度表 */
int wordp=0; /* 単語帳の最後 */
/******************************************/
/* 単語登録(すでに登録済みなら頻度+1) */
/******************************************/
void add_word(char *s) {
 int i;
 if (strlen(s)==0) return; /* 長さ0は登録しない */
 for (i=0; i<wordp; i++) { /* 登録済みかどうか調べる */
     if (strcmp(word[i],s)==0) {
         freq[i]++;
         break;
     }
 }
 if (i==wordp) { /* 登録されてなければ追加する */
     if ((word[wordp]=(char*)malloc(strlen(s)+1))==NULL) exit(1);
     strcpy(word[wordp],s);
     freq[wordp]=1;
     if (wordp<WORD_MAX-1) wordp++;
 }
}
/******************************/
/* ファイルから単語を切り出す */
/******************************/
void split_word(FILE *fp) {
    char buf[WORD_SIZE];
    int bufp=0;
    int key;
    int sp=0; /* 空白チェック用フラグ */
    while((key=fgetc(fp))!=EOF) {
        if (key==' ' && sp==0) {/* 空白の1個目は単語区切り文字とする */
            buf[bufp]='\0'; bufp=0; add_word(buf); sp=1;
        } else {
if( key=='.' || key== '!' || key=='?' || key=='"' || key=='\n' || key=='<' || key=='>' 
   || key==';' || key==':' || key=='+'|| key==')' || key=='(' || key=='`' || key=='*' || key=='[' || key==']' 
   || key=='#'){/* 特定の区切り文字は単語登録する */
if (sp==1) { /* 空白に続く場合は空白含めて登録する */
    buf[bufp]=key; if (bufp<WORD_SIZE-1) bufp++;
    buf[bufp]='\0'; bufp=0; add_word(buf); sp=0;
} else { 
    buf[bufp]='\0'; bufp=0; add_word(buf);
    buf[0]=key; buf[1]='\0'; add_word(buf);
}
} else {
    if (key == ',' || key == 0x0a || key == 0x0ff ){/* 普通の区切り文字 */
        buf[bufp]='\0'; bufp=0; add_word(buf); sp=0;
    } else { /* 区切り文字ではない文字(空白の2個目以降は区切り文字としない) */
        buf[bufp]=key; if (bufp<WORD_SIZE-1) bufp++;
        if (key != ' ') sp=0;
    }
}
        }
    }
    if (bufp>0) { /* 単語直後にEOFがきた場合 */
        buf[bufp]='\0'; add_word(buf);
    }
}
/******************/
/* 単語を表示する */
/******************/
void print_word(void) {
    int i;
    for (i=0; i<wordp; i++) {
        printf("%d [%s] %d\n",i,word[i],freq[i]);
    }
}
/************************************/
/* 単語用に確保したメモリを解放する */
/************************************/
void free_word(void) {
    int i;
    for (i=0; i<wordp; i++) {
        free(word[i]);
    }
}
/**********/
/* メイン */
/**********/
int main(int argc, char **argv) {
    FILE *fp;
    if (argc!=2) return -1; /* コマンドラインでファイル名指定 */ 
    if ((fp=fopen(argv[1],"r"))==NULL) return -1; /* ファイル開けない */
    split_word(fp); fclose(fp); /* 単語切り出し */
    print_word(); /* 単語表示 */
    free_word(); /* メモリ解放 */
    return 0;
}



コマンドラインからファイルを実行していますので、実行方法は
(1)コンパイル、リンクして、「(ファイル名).EXE」を作成する。
(2)コマンドプロンプト(DOS窓)を起動
(3)実行ファイルがあるフォルダに移動
(4)実行ファイルに読み込みたいテキストファイルを指定して実行です。
  http://www9.plala.or.jp/sgwr-t/c/sec11-4.htmlを参照して下さい。

よろしくお願いいたします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:qsort()を使い、頻出頻度順に表示させたい 3310 nop 2005/01/17 16:46:13
<子記事> Re:qsort()を使い、頻出頻度順に表示させたい 3311 RiSK 2005/01/17 21:41:36
<子記事> Re:qsort()を使い、頻出頻度順に表示させたい 3315 NykR 2005/01/17 23:43:27


No.3310

Re:qsort()を使い、頻出頻度順に表示させたい
投稿者---nop(2005/01/17 16:46:13)


>どなたかプログラムの追加をお願いいたします。 

それは質問ではありません。
ただの作成依頼です。
作成依頼でしたら、それなりの業者さんか、
知り合いのプログラマさんにお金を払って依頼して下さい。

ここは、そのような依頼をする所ではありません。


>後はqsort()を使い、頻出頻度順に表示させたいのですがポインタの理解に苦しみます。

では、まずはポインタの理解から始めてみては如何でしょうか?


この投稿にコメントする

削除パスワード

No.3311

Re:qsort()を使い、頻出頻度順に表示させたい
投稿者---RiSK(2005/01/17 21:41:36)


char *word[WORD_MAX]; /* 単語帳 */
int freq[WORD_MAX]; /* 頻度表 */
これらを構造体にまとめましょう。バラバラだとソートがめんどくさくなります。
そして,作った構造体の比較関数を作り,qsort を呼べば OK.


この投稿にコメントする

削除パスワード

No.3312

Re:qsort()を使い、頻出頻度順に表示させたい
投稿者---RiSK(2005/01/17 22:14:18)


>これらを構造体にまとめましょう。
typedef struct {
    char * word;
    int freq;
} WORD;

static WORD book[WORD_MAX];
static int wordp = 0;

>そして,作った構造体の比較関数を作り,qsort を呼べば OK.
static int CompareWord(const void * elem1, const void * elem2)
{
    const WORD * e1 = elem1;
    const WORD * e2 = elem2;
    return e2->freq - e1->freq;
}

void SortWords()
{
    qsort(book, wordp, sizeof(WORD), CompareWord);
}



この投稿にコメントする

削除パスワード

No.3314

Re:qsort()を使い、頻出頻度順に表示させたい
投稿者---RiSK(2005/01/17 23:42:07)


>void SortWords()

void SortWords(void) に訂正 (^^;;


この投稿にコメントする

削除パスワード

No.3315

Re:qsort()を使い、頻出頻度順に表示させたい
投稿者---NykR(2005/01/17 23:43:27)


>後はqsort()を使い、頻出頻度順に表示させたいのですがポインタの理解に苦しみます。
>どなたかプログラムの追加をお願いいたします。 

qsortは使ってませんが。

void print2(void)
{
  int f, i;
  int link[WORD_MAX];
  int index[WORD_MAX];

  for (f = 0; f < WORD_MAX; f++) {
    index[f] = -1;
  }

  for (i = 0; i < wordp; i++) {
    link[i] = index[freq[i]];
    index[freq[i]] = i;
  }

  for (f = 0; f < WORD_MAX; f++) {
    i = index[f];
    for ( ; i != -1; i = link[i]) {
      printf("%s--%d\n", word[i], freq[i]);
    }
  }
}



この投稿にコメントする

削除パスワード

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




掲示板提供:Real Integrity