掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

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

掲示板2

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

No.24238

qsortの使い方
投稿者---fuku(2005/11/19 11:08:16)


構造体のメンバの数値を使って降順に並べ替えるプログラムを
作っています
sampleとして

演算

複雑



複雑
演算

4

複雑
複雑

という sample.txt を作り、実行したところ

複雑 4
子 2
章 2
演算 2
4 1
4 1
1 1

という期待通りの結果が帰ってきました。
しかし、

複雑
演算




複雑
演算

基本

演算

4


という元ファイルを少しだけ変更した sample1.txt を使って実行したところ

複雑 2
演算 3
子 3
1 1
4 1
章 2
基本 1
的 1
4 1

という、並べ替えのされていない結果が帰ってきました
プログラムが悪いのか、サンプルファイルが悪いのかさえ、分かりません
何処が悪いのか分かりますでしょうか?
よろしくお願いします。
サンプルのため要素数は少なくしてありますが、将来は要素数を増やして
実行したいと思っていますので、クイックソートをしようしています。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct hinsi{         //名詞と頻度の構造体                

    char go[64];
    int count;
};
int cmp(const hinsi *x, const hinsi *y);   //降順で並べる(クイックソート)

int main(void)
{
    FILE* fin;
    char infile[32];
    int flag;
    int i = 0;
    int j = 0;
    struct hinsi meisi[100];
    for(j = 0; j < 100; j++)  meisi[j].count = 0;   //初期化


    printf("INファイル名-->");
    scanf("%s", infile);
    if((fin = fopen(infile, "r")) == NULL){
        printf("ファイルがありません\n");
        return 1;
    }
/*  読み込んで頻度を計算  */
    while(fscanf(fin, "%s", meisi[i].go) != EOF){
        flag = 1;
        for(j = 0; j < i; j++){
            if(!strcmp(meisi[j].go, meisi[i].go)){      //同じ名詞ならカウントを増やす

                meisi[j].count += 1;
                flag = 0;
                break;
            }
        }
        if(flag != 0){             //違う名詞なら新しく格納

            meisi[i].count += 1;
            i++;
        }
    }
/*  クイックソート降順で並べる  */
    qsort(meisi, i, sizeof(hinsi), (int(*)(const void*, const void*))cmp);

    for(j = 0; j < i; j++)
        printf("%s\t%d\n", meisi[j].go, meisi[j].count);
    
    fclose(fin);
    return 0;
}

int cmp(const hinsi *x, const hinsi *y)
{
    return (x->count < y->count ? 1 : 
            x->count < y->count ?  -1 : 0);
}




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:qsortの使い方 24240 επιστημη 2005/11/19 11:14:00
<子記事> Re:qsortの使い方 24241 まきじ 2005/11/19 11:29:31
<子記事> Re:qsortの使い方 24244 かずま 2005/11/19 15:07:27


No.24240

Re:qsortの使い方
投稿者---επιστημη(2005/11/19 11:14:00)


>プログラムが悪いのか、サンプルファイルが悪いのかさえ、分かりません
>何処が悪いのか分かりますでしょうか?

まずソート直前のデータをプリントし、正当か否かを確認してください。
どこが悪いかわからんなら、「どこまで正しいか」を調べるべし。



この投稿にコメントする

削除パスワード

No.24242

Re:qsortの使い方
投稿者---fuku(2005/11/19 11:50:08)


>まずソート直前のデータをプリントし、正当か否かを確認してください。
>どこが悪いかわからんなら、「どこまで正しいか」を調べるべし。

ありがとうございます
ご指摘の通り、ソート前とソート後を出力するようにしてみました
正しく動作したsample.txt
--結果--
並べ替える前

演算 2
子 2
複雑 4
1 1
4 1
章 2
4 1
並べ替えた後

複雑 4
子 2
章 2
演算 2
4 1
4 1
1 1
--結果--

正しく動作しなかったsample1.txt
--結果--
並べ替える前

複雑 2
演算 3
子 3
1 1
4 1
章 2
基本 1
的 1
4 1
並べ替えた後

複雑 2
演算 3
子 3
1 1
4 1
章 2
基本 1
的 1
4 1
--結果--
でした。
正しく動作しない方は、ソート前とソート後で
全く変化がないです
ステップインで一行ずつ実行してみたところ
qsort は確かに呼び出されています


補足
環境はコンパイラ visual studio.net2003
OS windows XP
qsort は使い方が分からなかったので、実装例が載っているサイトを
アレンジして使っています



この投稿にコメントする

削除パスワード

No.24241

Re:qsortの使い方
投稿者---まきじ(2005/11/19 11:29:31)


>int cmp(const hinsi *x, const hinsi *y);

struct が抜けている。(他にもある)

>return (x->count < y->count ? 1 : x->count < y->count ? -1 : 0);

x->count < y->count が偽の時 また x->count < y->count をするのですか?


この投稿にコメントする

削除パスワード

No.24243

Re:qsortの使い方
投稿者---fuku(2005/11/19 11:58:06)


>>int cmp(const hinsi *x, const hinsi *y);
>
>struct が抜けている。(他にもある)
>
>>return (x->count < y->count ? 1 : x->count < y->count ? -1 : 0);
>
>x->count < y->count が偽の時 また x->count < y->count をするのですか?

早いお返事ありがとうございます
サイトの実装例でしたので、疑うことなくそのまま使っていました
自分で確認が大切ですね・・
ご指摘の部分を

if(x->count < y->count) return 1;
else if(x->count > y->count) return -1;
else return 0;
にしたところ
正しく動作しました

本当にありがとうございます



この投稿にコメントする

削除パスワード

No.24244

Re:qsortの使い方
投稿者---かずま(2005/11/19 15:07:27)


> サンプルのため要素数は少なくしてありますが、将来は要素数を増やして
> 実行したいと思っていますので、クイックソートをしようしています。

ひとつの要素のサイズ sizeof(struct hinsi) が 68バイト程度で、
ソート中に交換するには大きすぎて時間がかかります。
次のようにしてみてはどうでしょう。初期化も不要で時間が無駄になりません。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define N  100

typedef struct {
    char *go;
    int count;
} hinsi;

int cmp(const void *x, const void *y);

int main(void)
{
    hinsi meisi[N];  char buf[256];  int i, n = 0;  FILE* fin;

    printf("INファイル名-->"), scanf("%255s", buf);
    fin = fopen(buf, "r");
    if (!fin) { puts("ファイルがありません"); return 1; }

    while (fscanf(fin, "%255s", buf) == 1) {
        for (i = 0; i < n && strcmp(meisi[i].go, buf); i++) ;
        if (i < n) meisi[i].count += 1;
        else {
            if (n++ == N) { puts("データが多すぎる"); return 1; }
            meisi[i].count = 1;
            meisi[i].go = strdup(buf);
            if (!meisi[i].go) { puts("メモリが足りない"); return 1; }
        }
    }
    fclose(fin);

    qsort(meisi, n, sizeof(hinsi), cmp);

    for (i = 0; i < n; i++)
        printf("%s\t%d\n", meisi[i].go, meisi[i].count);
    
    return 0;
}

int cmp(const void *x, const void *y)
{
    const hinsi *a = x, *b = y;
    return (a->count > b->count) ? -1 : (a->count < b->count);
}

# ご質問とは関係ありませんが、ひさびさに「字下げ」されたプログラムの
# 投稿で気持ちよく拝見できました。
#
# 最近、字下げの無いプログラムを平気で投稿する質問が多くて、私は全部
# 無視しています。「Zeller の公式」などは、すぐに回答をつけて、あんなに
# スレッドが長くなることは無かったと思うんですが、なぜ字下げしないんで
# しょうか? 字下げをしていないプログラムは人の読めるものではありません。
# それで平気だということは、自分でプログラムを理解する気が無いし、人に
# も理解してもらおうという気が無いものと思えてなりません。
# 質問とは関係の無い愚痴で申し訳ありませんでした。


この投稿にコメントする

削除パスワード

No.24245

Re:qsortの使い方
投稿者---επιστημη(2005/11/19 15:16:36)


freeし損ねてます。この例では実害はありませんけど念のため。



この投稿にコメントする

削除パスワード

No.24246

Re:qsortの使い方
投稿者---fuku(2005/11/19 15:53:50)


かずまさん
>ひとつの要素のサイズ sizeof(struct hinsi) が 68バイト程度で、
>ソート中に交換するには大きすぎて時間がかかります。
>次のようにしてみてはどうでしょう。初期化も不要で時間が無駄になりません。

επιστημηさん
>freeし損ねてます。この例では実害はありませんけど念のため。

的確なアドバイスをありがとうございました
良い手本まで載せていただきありがとうございます。
コピーして勉強に励みますね。
また何かあればお願いします☆


この投稿にコメントする

削除パスワード

No.24247

Re:qsortの使い方
投稿者---fuku(2005/11/19 15:55:16)


まじきさんが抜けていました
大変失礼いたしました



この投稿にコメントする

削除パスワード

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