掲示板利用宣言

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

 私は

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

掲示板2

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

No.25791

連続する文字の出現頻度
投稿者---スケイス(2006/01/29 18:10:47)


#define TNG_SIZE 3ここで設定した文字の中で頻度が高いものを出力したいのですが、strlenを使い、かえってくる文字が==TNG_SIZEだったら出力するように考えました。しかしコンパイルは行えるのですが、実行するとSegmentation fault (core dumped)このようになってしまいます。アドバイスのほうよろしくお願いします。
目標とする出力結果。
_th
the
he_
_of
of_
などを出力したいのです。
_←これはスペースです。



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 7000 //word_tableの大きさ
#define YUSEN_JYUNI 6137    //優先順位
#define TNG_SIZE 3    //単語のサイズ

    struct word_count{
    char *word;  //単語
    int count;    //頻度
    };

int main(int argc, char *argv[])
{
    FILE *fp;
    struct word_count word_table[TABLE_SIZE]; //単語と頻度を格納する配列
    char line[256],*token,*moji,*p;
    int i,j,table_size,find,bangou;
    table_size = 0;

    //ファイル入力にエラーが生じた場合
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("file open error!!\n");
        exit(1);
    }

    while(fgets(line, 256, fp) != 0)
    {
        token = strtok(line, " ");
        for(;token!= NULL;token = strtok(NULL, " "))
        {
            find = 0;
            //word_tableとの照合
            for(i = 0; i < table_size; i++)
            {
                //一致する単語を見つけた場合
                if (strcmp(token, word_table[i].word) == 0)
                {
                    word_table[i].count++;
                    find = 1;
                    break;
                }
            }
                //word_table中に一致する単語がなかった場合
                if (find == 0)
                {
                    word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                    strcpy(word_table[table_size].word,token);
                    strcat(word_table[table_size].word,token);
                    word_table[table_size].count = 1;
                    table_size++;
                }
        }
    }
    fclose(fp);

    //オリジナルソートで出現頻度順にソート
    for(i = 0; i < table_size; i++)
    {
        for(j = table_size-1; j >= i; j--)
        {

            if(word_table[i].count < word_table[j].count)
            {
                moji = word_table[i].word;
                word_table[i].word = word_table[j].word;
                word_table[j].word = moji;
                bangou = word_table[i].count;
                word_table[i].count = word_table[j].count;
                word_table[j].count = bangou;
            }
        }
    }

    //word_tableを出力//
    for (i = 0; i < YUSEN_JYUNI && i < table_size; i++)
    {
        if(i < table_size && strlen(word_table[i].word) == TNG_SIZE )
        printf("%4d: %s\n", word_table[i].count , word_table[i].word);
    }

    return 0;
}





この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:連続する文字の出現頻度 25792 επιστημη 2006/01/29 18:23:49
<子記事> Re:連続する文字の出現頻度 25793 επιστημη 2006/01/29 18:30:03


No.25792

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 18:23:49)


> #define TNG_SIZE 3ここで設定した文字の中で頻度が高いものを出力したいのですが、strlenを使い、かえってくる文字が==TNG_SIZEだったら出力するように考えました。
> しかしコンパイルは行えるのですが、実行するとSegmentation fault (core dumped)このようになってしまいます。

そんな訊きかたでは同じ注意を何度も受けますよ。
- どこまでうまくいって、どこからヘンになりますか?
- たとえばソート部をとっぱらえば動きますか?
- 「かえってくる文字が==TNG_SIZEだったら」をやらなければどうなりますか?
- 小さなファイルを食わせたらどうですか?

などなど。
「デバッグのしかた」をおぼえましょう。
トラブルのたびに掲示板にお伺いでは埒が開かない。



この投稿にコメントする

削除パスワード

No.25797

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 21:17:29)


επιστημηさん回答ありがとうございます。
どこまでうまくいったのかは、printf()を間にいれて動いてるのを報告すればいいのでしょうか?
ソートの部分は関係ありませんでした。
小さなファイルでやったらやはり結果と結果の途中にスペースが入っていました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 7000 //word_tableの大きさ
#define YUSEN_JYUNI 50  //優先順位
#define TNG_SIZE 3    //単語のサイズ

    struct word_count{
    char *word;  //単語
    int count;    //頻度
    };

int main(int argc, char *argv[])
{
    FILE *fp;
    struct word_count word_table[TABLE_SIZE]; //単語と頻度を格納する配列
    char line[256],*token,*moji,*p;
    int i,j,table_size,find,bangou;
    table_size = 0;

    //ファイル入力にエラーが生じた場合
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("file open error!!\n");
        exit(1);
    }

    while(fgets(line, 256, fp) != 0)
    {
        token = strtok(line, " ");
        for(;token!= NULL;token = strtok(NULL, " "))
        {
            find = 0;
            //word_tableとの照合
            for(i = 0; i < table_size; i++)
            {
                //一致する単語を見つけた場合
                if (strcmp(token, word_table[i].word) == 0)
                {
                    word_table[i].count++;
                    find = 1;
                    break;
                }
            }
                //word_table中に一致する単語がなかった場合
                if (find == 0)
                {
                    word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                    strcpy(word_table[table_size].word,token);
                    word_table[table_size].count = 1;
                    table_size++;
                }
        }
    }
    fclose(fp);

    //オリジナルソートで出現頻度順にソート
    for(i = 0; i < table_size; i++)
    {
        for(j = table_size-1; j >= i; j--)
        {
            if(word_table[i].count < word_table[j].count)
            {
                moji = word_table[i].word;
                word_table[i].word = word_table[j].word;
                word_table[j].word = moji;
                bangou = word_table[i].count;
                word_table[i].count = word_table[j].count;
                word_table[j].count = bangou;
            }
        }
    }

    //word_tableを出力//
    for (i = 0; i < YUSEN_JYUNI && i < table_size; i++)
    {
        if(i < YUSEN_JYUNI && i < table_size && strlen(word_table[i].word)== TNG_SIZE )
        printf("%4d: %s\n", word_table[i].count , word_table[i].word);
    }

    return 0;
}




大きなファイルでやると優先順位50に設定しても15で止まってしまいました。後、_thなどのスペースと文字の合体しているものが引っかからないということも分かりました。

実行結果(小さいファイル)
./hindo4.exe p.txt
3: to

1: the
(大きいファイル)

2109: the
1218: and
605: was
566: his
418: had
352: you
287: for
264: him
190: The
164: but
163: all
152: man
151: her
150: not
140: one

TNG_SIZEの指定無し。
2498:

2109: the
1218: and
1142: of
1008: to
922: I
901: a
649: in
605: was
599: he
580: that
566: his
446: it
418: had
352: you
291: with
288: as
287: for
286: which
283: is
277: at
264: him
255: my
252: have
247: the

237: be
203: said
203: me
190: The
187: on
183: upon
174: s
173: this
171: He
164: but
163: all
160: from
152: man
151: her
150: not
149: there
148: were
144: by
142: It
140: one
136: them
136: been
133: we
131: up
129: so



この投稿にコメントする

削除パスワード

No.25803

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 21:40:28)


ところで table_size の初期値は?



この投稿にコメントする

削除パスワード

No.25804

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 21:45:03)


table_size = 0;

0です。


この投稿にコメントする

削除パスワード

No.25811

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:11:34)


>table_size = 0;
>
>0です。

コードのどこに table_size = 0; と書いてありますか?



この投稿にコメントする

削除パスワード

No.25867

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/31 15:31:45)


>コードのどこに table_size = 0; と書いてありますか?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 10000    //word_tableの大きさ
#define YUSEN_JYUNI 50   //優先順位

    struct word_count{
    char *word;  //単語
    int count;    //頻度
    };

int main(int argc, char *argv[])
{
    FILE *fp;
    struct word_count word_table[TABLE_SIZE]; //単語と頻度を格納する配列
    char line[256],*token,*moji;
    int i,j,table_size,find,bangou;
    table_size = 0;←ここにかいてあえいます。



この投稿にコメントする

削除パスワード

No.25806

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 21:52:53)


>小さなファイルでやったらやはり結果と結果の途中にスペースが入っていました。

デバッグのやり方を知らんみたいやなぁ…

> printf("%4d: %s\n", word_table[i].count , word_table[i].word);

"%4d: [%s]\n" とすれば、空白が現れる理由がわかる。




この投稿にコメントする

削除パスワード

No.25809

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 21:59:03)


これはスペースが入ってることですか。
空白はスペースだったんですね。


この投稿にコメントする

削除パスワード

No.25810

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:00:57)


>これはスペースが入ってることですか。
>空白はスペースだったんですね。

実行結果はどうなりました?

2: [the
]

みたいな出力がでたんじゃない? だったら理由がわかるでしょ。




この投稿にコメントする

削除パスワード

No.25868

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/31 15:32:49)


改行だったんですね。ありがとうございました。




この投稿にコメントする

削除パスワード

No.25793

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 18:30:03)


word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
strcpy(word_table[table_size].word,token);
strcat(word_table[table_size].word,token); ←これは何のため?




この投稿にコメントする

削除パスワード

No.25799

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 21:20:41)


strcat(word_table[table_size].word,token); 

これはスペースを含めた文字のための出力のために必要だとおもいつけました。
_th'\0'この用に連結させて、_thとして出力するためにつけたのですが、これがコンパイルエラーの元だったみたいです。


この投稿にコメントする

削除パスワード

No.25800

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 21:28:15)


>strcat(word_table[table_size].word,token);
>これはスペースを含めた文字のための出力のために必要だとおもいつけました。

わかんない。 token:"_th"とすると word_table[..].word:"_th_th" となるが、それでいいのね?
これでいいとすると、mallocした領域が小さすぎます。

もっといえば、空白を区切りにstrtokするのだから、tokenには空白を含みません。

>_th'\0'この用に連結させて、_thとして出力するためにつけたのですが、これがコンパイルエラーの元だったみたいです。

コンパイルエラー? なぜ?



この投稿にコメントする

削除パスワード

No.25802

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 21:40:20)


>strcat(word_table[table_size].word,token);
すいませんコンパイルエラではなく実行エラーでした。
これをけして実行したらできました。
_thでしたすいません。

        token = strtok(line, "\n");
        for(;token!= NULL;token = strtok(NULL, "\n"))


ここを改行にしたら、小さいファイルだと_toとかを検出できました。
しかいファイルが大きくなると実行しても出力されません。
επιστημηさん、_th'\0'と_th'\n'のこのふたつのように、スペースではなくてヌル文字と改行で判断させることはできないでしょうか?


(小さいファイルの中身)
_to
_to
tomo
(実行結果)
2:_to

strtokこの中に'\0'を指定してもヌル文字は判定されていません。


この投稿にコメントする

削除パスワード

No.25808

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 21:56:05)


> _th'\0'と_th'\n'のこのふたつのように、スペースではなくてヌル文字と改行で判断させることはできないでしょうか?

ごめん、なにがやりたいんだかさっぱりわからん。



この投稿にコメントする

削除パスワード

No.25812

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 22:13:33)


説明が下手でごめんなさい。><;
連続する文字をカウントし、出現頻度が多い順に出力させたいのです。
TNG_SIZEが3だったら、出力結果は、
_th
the
などのように出力したいのです。

しかし以下のように
        token = strtok(line, " \n");
        for(;token!= NULL;token = strtok(NULL, " \n"))

スペースを区切り文字にしてしまうと出力結果は、
the
and
のようにスペースを含んでるものがヒットしなくなるのです。

私は、_th'\0'←このようにヌル文字で判断して、出力結果を
_th
などのようにできると考えたのです。こうすることによってスペースは文字としてカウントでき、意図する結果になると考えました。

しかし実際にはヌル文字を条件式に加えても出力結果はかわりませんでした。他に出力結果を
_th
the
he_
_of
のようにさせるにはどのような方法があるのでしょうか?^^;



この投稿にコメントする

削除パスワード

No.25814

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:17:22)


>連続する文字をカウントし、出現頻度が多い順に出力させたいのです。
>TNG_SIZEが3だったら、出力結果は、
>_th
>the
>などのように出力したいのです。

ちょっとマテ。では単語に区切る"区切り方"をきちんと定義してほしい。
特に空白の扱い。単に空白や改行で区切るだけでは単語に空白を含まない。



この投稿にコメントする

削除パスワード

No.25816

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 22:25:50)


すいません、区切り方の前に質問させてください><;
とんでもない勘違いをしていたのかもしれません。
これはBrownコーパス(英国の新聞記事)の文字出現頻度大文字と
小文字を区別。_は空白
3字組み
_th
the
he_
_of
ed_
_an
nd_
なんですけど、スペースと空白は意味が違うのでしょうか?^^;


この投稿にコメントする

削除パスワード

No.25817

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:31:33)


>すいません、区切り方の前に質問させてください><;
>とんでもない勘違いをしていたのかもしれません。
>これはBrownコーパス(英国の新聞記事)の文字出現頻度大文字と
>小文字を区別。_は空白
>3字組み
>_th
>the
>he_
>_of
>ed_
>_an
>nd_
>なんですけど、スペースと空白は意味が違うのでしょうか?^^;

通常スペースと空白は同じ。

で、"my name is same as a name of a month" を単語に区切ってもらいたいのだが。
"my" "name" "is" "same" "as" ... ではダメなんでしょ? ならばどう区切る?

それが僕に伝わってこないので答に窮しているんだけど。



この投稿にコメントする

削除パスワード

No.25820

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 22:41:03)


私なりに考えたのですが、これは以下のようなことだと思います。
monthだったら
_th

andだったら
and

this_だったら
is_

だと思うのですが伝わりましたか?><;
説明へたでごめんなさい。


この投稿にコメントする

削除パスワード

No.25821

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:41:47)


>私なりに考えたのですが、これは以下のようなことだと思います。
>monthだったら
>_th
>
>andだったら
>and
>
>this_だったら
>is_
>
>だと思うのですが伝わりましたか?><;

伝わりません。ルールを示してください。




この投稿にコメントする

削除パスワード

No.25823

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 22:47:58)


たとえば、Do you like apple?だとしたら、
このとき最初に取得するのが
Do_
次が
o_y
_yo
you
ou_
u_l

のように見ていくのですが、この説明で伝わりましたか?><;
3文字で1字ずつずらしてまた3文字ずつみていってその中で頻度が高いのを出力したいのです。


この投稿にコメントする

削除パスワード

No.25825

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 23:03:31)


>3文字で1字ずつずらしてまた3文字ずつみていってその中で頻度が高いのを出力したいのです。

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

#define TOKEN_SIZE 3

int main() {
  int i;
  char token[TOKEN_SIZE+1];
  const char* input = "Do you like apple?";
  int len = strlen(input) - TOKEN_SIZE;
  token[TOKEN_SIZE] = '\0';
  for ( i = 0; i <= len; ++i ) {
    strncpy(token, input+i, TOKEN_SIZE);
    printf("[%s]\n", token);
  }
  return 0;
}

実行結果:
[Do ]
[o y]
[ yo]
[you]
[ou ]
[u l]
[ li]
[lik]
[ike]
[ke ]
[e a]
[ ap]
[app]
[ppl]
[ple]
[le?]

これでいい?



この投稿にコメントする

削除パスワード

No.25826

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 23:15:34)


はいそういう意味です。それで優先順位が上から50のものを出力するということです。
今までのプログラムを改良すれば作れるでしょうか?それともまったく別に作り直したほうがいいのでしょうか?


この投稿にコメントする

削除パスワード

No.25827

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 23:21:14)


>はいそういう意味です。それで優先順位が上から50のものを出力するということです。

そろそろ"質問の下手さ"に気づいてほしい。
こんなにスレッドが膨らむのは"やりたいことを正確に"表現できていないからだ。
だからあれやこれやと訊き返さなくてはならなくなる。

>今までのプログラムを改良すれば作れるでしょうか?それともまったく別に作り直したほうがいいのでしょうか?

お好きにどうぞ。
あなたがどこまでわかっているのかわからないのでどちらとも言えない。



この投稿にコメントする

削除パスワード

No.25828

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 23:29:41)


説明が下手ですいません。これしかいえません。両方検討してみます。


この投稿にコメントする

削除パスワード

No.25829

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 23:36:54)


>説明が下手ですいません。これしかいえません。両方検討してみます。

ひとつだけ懸念事項。
"一文字ずつずらしながらファイルの末尾まで"ということは、
最悪ケースでは単語表の個数(table_size)がファイルにある
総文字数とほぼ同数になる。
だから大きなファイルを食わすと確実に破裂する。



この投稿にコメントする

削除パスワード

No.25830

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 23:59:16)


アドバイスありがとうございました。私もそう思いました。#defineをものすごく大きい数に変えました。
一つにするのは大変だということも分かりました。


この投稿にコメントする

削除パスワード

No.25848

Re:連続する文字の出現頻度
投稿者---kz3(2006/01/30 09:58:49)


>アドバイスありがとうございました。私もそう思いました。#defineをものすごく大きい数に変えました。

根本解決にはなっていないですね・・・。

επιστημηさんが言いたかったのは
静的に用意したバッファでは最悪のケースに対応できない
ということだと思うのですが、それは伝わっているのかな?


この投稿にコメントする

削除パスワード

No.25869

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/31 15:35:49)


>ということだと思うのですが、それは伝わっているのかな?

そおいう意味だったんですか。考えて見ます。


この投稿にコメントする

削除パスワード

No.25838

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 01:05:25)


すいません質問です。ここはなにをしているのでしょうか?^^;
   strncpy(token, input+i, TOKEN_SIZE);




この投稿にコメントする

削除パスワード

No.25839

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/30 01:09:03)


>すいません質問です。ここはなにをしているのでしょうか?^^;
> strncpy(token, input+i, TOKEN_SIZE);

i だけずらして TOKEN_SIZE 文字分 token にコピーしてます。
# 関数マニュアル/リファレンス読んでます?



この投稿にコメントする

削除パスワード

No.25840

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 01:19:46)


http://www9.plala.or.jp/sgwr-t/lib/strncpy.html
こちらを見てみましたが、よく分かりませんでした。
TOKEN_SIZEはnで、+iだけずらしてtokenにコピーすることが分かりませんでした。επιστημηさんありがとうございました。私みたいな初心者でも、επιστημηさんの分かりやすい説明だとよくわかって勉強になります。日本語は下手なので責めないで下さい><;

strncpy(token, input+i, TOKEN_SIZE);
この使い方はすごくいいですね。ものすごく参考になりました。


この投稿にコメントする

削除パスワード

No.25841

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/30 01:50:34)


>strncpy(token, input+i, TOKEN_SIZE);
>この使い方はすごくいいですね。ものすごく参考になりました。

3文字tokenの切り出しはこれでよろしいな。
ならば単語表に乗せてソートして出力すれば完了。
今のコードをちょちょっといぢくればできあがり。




この投稿にコメントする

削除パスワード

No.25843

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 02:52:49)


流れは分かりましたが、まだ理解できていません。
const char *input="123 456 654 789 123 456 654 789";
ここのところを、ファイルから読み込ませるようにして、ソートして出力すればいいと思うのですが、読み込ませることができません。
一文字ずつfscanfで読み取っていこうとおもっているのですが、うまくいきません。
    while(fgets(line, 256, fp) != 0)
    {
        fscanf(fp,"%s",&input);

文法がおかしいかみてください。頭悪くてすいません^^;



この投稿にコメントする

削除パスワード

No.25844

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 03:03:09)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 10000    //word_tableの大きさ
#define YUSEN_JYUNI 50   //優先順位
#define TNG_SIZE 3      //文字サイズ

int main(int argc, char *argv[])
{
    FILE *fp;
    char token[TNG_SIZE+1],*input;
    int i,j

//  const char *input="123 456 654 789 123 456 654 789";

    //ファイル入力にエラーが生じた場合
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("file open error!!\n");
        exit(1);
    }

    while(fgets(line, 256, fp) != 0)
    {
        fscanf(fp,"%c",&input);
        
        int len = strlen(input) - TNG_SIZE;
        token[TNG_SIZE] = '\0';
        
        
    for(i = 0; i < table_size; i++)
    {
        for(j = table_size-1; j >= i; j--)
        {
            if(word_table[i].count < word_table[j].count)
            {
                moji = word_table[i].word;
                word_table[i].word = word_table[j].word;
                word_table[j].word = moji;
                bangou = word_table[i].count;
                word_table[i].count = word_table[j].count;
                word_table[j].count = bangou;
            }
        }
    }
    for ( i = 0; i< YUSEN_JYUNIi && <= len; i++ )
    {
        strncpy(token, input+i, TNG_SIZE);
        printf("[%s]\n", token);
    }
    return 0;
}



おおまかな流れはこのような感じでしょうか?


この投稿にコメントする

削除パスワード

No.25845

Re:連続する文字の出現頻度
投稿者---ぽへぇ(2006/01/30 05:30:22)


>    char token[TNG_SIZE+1],*input;
>        fscanf(fp,"%c",&input);

なにも分かってない。入門書からやり直し。

>おおまかな流れはこのような感じでしょうか?
やれやれ。以下と比べて、どこがどう足りないと思う?

while(ファイルが終了になるまで 一行読み込む) {
    一行を3文字毎に分ける
    その3文字がテーブルにあれば出現頻度に+1する
    なければテーブルにその3文字を追加する
}

出現頻度順にソートする
表示する

>文法がおかしいかみてください。頭悪くてすいません^^;
フェイスマーク(^^;)が多くないか?まじめな話の中で連発すると
不真面目ととられるよ。




この投稿にコメントする

削除パスワード

No.25852

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 23:00:45)


すいませんでした。かなり間違っていました。


この投稿にコメントする

削除パスワード

No.25846

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/30 05:37:53)


> while(fgets(line, 256, fp) != 0)
> {
>  fscanf(fp,"%s",&input);

ちょっとマテ。 3文字ずつ区切るんじゃなかったのか?



この投稿にコメントする

削除パスワード

No.25847

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/30 05:42:20)


> strncpy(token, input+i, TOKEN_SIZE);
> この使い方はすごくいいですね。ものすごく参考になりました。

これは一体なんだったの?

>一文字ずつfscanfで読み取っていこうとおもっているのですが、うまくいきません。

…まただ orz
「うまくいきません」の一言で済ますなってあれほど注意したのに。



この投稿にコメントする

削除パスワード

No.25853

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 23:02:30)


すいませんお時間ください。fscanfは勘違いしていました。


この投稿にコメントする

削除パスワード

No.25860

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/31 06:32:20)


>3文字tokenの切り出しはこれでよろしいな。
>ならば単語表に乗せてソートして出力すれば完了。
>今のコードをちょちょっといぢくればできあがり。

C++で書いてみた:

#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>

#define YUSEN_JYUNI  50  //優先順位

#define TOKEN_SIZE    3  //文字サイズ


struct word_count {
  std::string word;
  int         count;
  word_count(const std::string& w) : word(w), count(1) {}
};

struct same_word : std::unary_function<word_count, bool> {
  std::string target;
  same_word(const std::string& t) : target(t) {}
  bool operator()(const word_count& wc) const {
    return wc.word == target;
  }
};

inline bool operator<(const word_count& a, const word_count& b) {
  return a.count == b.count ? (a.word > b.word) : (a.count > b.count);
}

int main(int argc, char *argv[]) {

  std::vector<word_count> word_table;

  /* 入力 */
  {

    FILE *fp;
    char input[256];

    if ( (fp = fopen(argv[1], "r")) == NULL ) {
        printf("file open error!!\n");
        exit(1);
    }

    while ( fgets(input, 256, fp) != NULL ) {
        char token[TOKEN_SIZE+1];
        int len = strlen(input);
        token[TOKEN_SIZE] = '\0';
        if ( input[len-1] == '\n' ) {
            input[len-1] = '\0';
        }
        len = strlen(input) - TOKEN_SIZE;
        for ( int i = 0; i <= len; ++i ) {
            strncpy(token, input+i, TOKEN_SIZE);
            std::vector<word_count>::iterator iter = 
              std::find_if(word_table.begin(), word_table.end(), same_word(token));
            if ( iter == word_table.end() ) {
              word_table.push_back(word_count(token));
            } else {
              iter->count++;
            }
        }
    }
  }

  /* ソート */
  std::sort(word_table.begin(), word_table.end());

  /* 出力 */
  {
    int i = 0;
    for ( std::vector<word_count>::const_iterator iter = word_table.begin();
          i < YUSEN_JYUNI && iter != word_table.end(); ++i, ++iter) {
        printf("%4d: [%s]\n", iter->count, iter->word.c_str());
    }
  }

  return 0;
}






この投稿にコメントする

削除パスワード

No.25861

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/31 07:43:08)


pure C++化する。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

#define YUSEN_JYUNI  50  //優先順位
#define TOKEN_SIZE    3  //文字サイズ

struct word_count {
  std::string word;
  int         count;
  word_count(const std::string& w) : word(w), count(1) {}
};

struct same_word {
  std::string target;
  same_word(const std::string& t) : target(t) {}
  bool operator()(const word_count& wc) const {
    return wc.word == target;
  }
};

inline bool operator<(const word_count& a, const word_count& b) {
  return a.count == b.count ? (a.word > b.word) : (a.count > b.count);
}

int main(int argc, char *argv[]) {

  std::vector<word_count> word_table;

  // 入力
  if ( argc != 2 ) {
    return 1;
  }

  std::ifstream stream(argv[1]);
  std::string input;

  if ( !stream.is_open() ) {
      std::cerr << "file open error!!\n";
      return 1;
  }

  // 一行ずつ読み、
  while ( std::getline(stream, input) ) {
    std::string token;
    // 3文字ずつ切り分け、
    for ( std::string::size_type pos = 0; 
          (token = input.substr(pos, TOKEN_SIZE)).size() == TOKEN_SIZE; 
          ++pos ) {
      // 表になければ追加、あればカウント・アップ
      std::vector<word_count>::iterator iter = 
      std::find_if(word_table.begin(), word_table.end(), same_word(token));
      if ( iter == word_table.end() ) {
        word_table.push_back(word_count(token));
      } else {
        iter->count++;
      }
    }
  }

  // ソート
  std::sort(word_table.begin(), word_table.end());

  // 出力
  int i = 0;
  for ( std::vector<word_count>::const_iterator iter = word_table.begin();
        i < YUSEN_JYUNI && iter != word_table.end(); ++i, ++iter) {
    printf("%4d: [%s]\n", iter->count, iter->word.c_str());
  }

  return 0;
}





この投稿にコメントする

削除パスワード

No.25863

Re:連続する文字の出現頻度
投稿者---かずま(2006/01/31 09:40:52)


> pure C++化する。

>     printf("%4d: [%s]\n", iter->count, iter->word.c_str());

pure C++ ってどういう意味ですか?

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>

#define TOP  50            //優先順位
#define LEN   3            //文字サイズ

using std::string;

struct word_count {
    string word;
    int    count;
    word_count(const string& w, int n) : word(w), count(n) {}
};

inline bool operator<(const word_count& a, const word_count& b)
{
    return (a.count == b.count) ? (a.word < b.word) : (a.count > b.count);
}

int main(int argc, char *argv[])
{
    std::map<string, int> word_map;
    std::vector<word_count> word_table;

    if (argc != 2) return 1;
    std::ifstream stream(argv[1]);
    if (!stream) return std::cerr << "file open error!!\n", 1;

    string input, token;
    while (std::getline(stream, input))
        for (int i = 0; (token = input.substr(i, LEN)).size() == LEN; ++i)
             ++word_map[token];

    for (std::map<string, int>::const_iterator it = word_map.begin();
            it != word_map.end(); ++it)
        word_table.push_back(word_count(it->first, it->second));

    std::sort(word_table.begin(), word_table.end());

    int n = word_table.size();
    if (n > TOP) n = TOP;
    for (int i = 0; i < n; i++)
        std::cout << std::setw(4) << word_table[i].count << ": [" << word_table[i].word << "]\n";
}



この投稿にコメントする

削除パスワード

No.25878

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/31 19:19:19)


> pure C++化する。
> printf("%4d: [%s]\n", iter->count, iter->word.c_str());
> pure C++ ってどういう意味ですか?

あらら、printfが残ってました _o/L




この投稿にコメントする

削除パスワード

No.25849

Re:連続する文字の出現頻度
投稿者---nop(2006/01/30 10:18:36)


> 日本語は下手なので責めないで下さい><;

それは只の言い訳では?

そもそも、他人に母国語で正確に伝える事の出来ない処理を、
拙いC言語でコンピュータに伝えられると思いますか?

日本語が下手だと自覚しているのでしたら、
まずは、日本語をしっかり勉強すべきです。
C言語も一種の言葉です。

・自分は何を伝えたいのか?
・自分の意志を如何にして伝えるか?

日本語でもC言語でも大事な事です。
これを疎かにするから理解出来ないのでは無いですか?


この投稿にコメントする

削除パスワード

No.25854

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/30 23:03:06)


申し訳ありませんその通りです。


この投稿にコメントする

削除パスワード

No.25822

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/29 22:43:29)


>私なりに考えたのですが、これは以下のようなことだと思います。

"思います"ではコードに起こせません。
あなたがどう思って書いたコードかなんて知る由もありませんから。



この投稿にコメントする

削除パスワード

No.25824

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/29 22:48:37)


すいませんでした。><;




この投稿にコメントする

削除パスワード

No.25877

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/31 18:09:48)


>while(fgets(line, 256, fp) != 0) {
一行を3文字毎に分ける
その3文字がテーブルにあれば出現頻度に+1する
なければテーブルにその3文字を追加する
}

ぽへぇ様より、このように回答をいただいたのですが、どのような条件式にすれば、3文字ずつ
にわけてテーブルに格納できるのか方法が分かりません。。

今までの単語の場合は、改行とスペースで区切って単語として格納していました。
token = strtok(line, " \n");
for(;token!= NULL;token = strtok(NULL, " \n"))

以下単語の格納ソース
    while(fgets(line, 256, fp) != 0)
    {
        token = strtok(line, " \n");
        for(;token!= NULL;token = strtok(NULL, " \n")){
            find = 0;
            //word_tableとの照合
            for(i = 0; i < table_size; i++){
                //一致する単語を見つけた場合
                if (strcmp(token, word_table[i].word) == 0){
                    word_table[i].count++;
                    find = 1;
                    break;
                }
            }
                //word_table中に一致する単語がなかった場合
                if (find == 0){
                    word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                    strcpy(word_table[table_size].word,token);
                    word_table[table_size].count = 1;
                    table_size++;
                }
        }
    }


>一行を3文字毎に分ける
i だけずらして TOKEN_SIZE 文字分 token
strncpy(token, input+i, TOKEN_SIZE);

επιστημη様より、このような回答をいただいたのですが、この3文字に区切った
文字を格納する方法が分かりません。

私なりの考えは、まず一行を読み込み、初めの3文字を読み込んで一字ずらしてまた3文字読み込んでを繰り返し、それぞれ格納していきます。
はじめは絶対にテーブルの中に文字が無いので、+1してカウントをし、さらに同じ形の3文字が現れたら、2,3,4とカウントしていきます。
それぞれの3文字のパターンが出現したら、それぞれカウントしていきます。

どなたかお分かりになる方、ご教授のほどよろしくお願い致します。





この投稿にコメントする

削除パスワード

No.25880

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/01/31 19:25:52)


>>一行を3文字毎に分ける
>i だけずらして TOKEN_SIZE 文字分 token
>strncpy(token, input+i, TOKEN_SIZE);
>
>επιστημη様より、このような回答をいただいたのですが、この3文字に区切った
>文字を格納する方法が分かりません。

え? token には3文字に区切ったやつが入ってるんだから、
これをそのまま表に乗っければいいじゃん。

 char token[TOKEN_SIZE+1];
 char input[256];
 token[TOKEN_SIZE] = '\0';
 while ( ファイルから一行、inputに読み込む ) {
  int len = strlen(input) - TOKEN_SIZE;
  for ( i = 0; i <= len; ++i ) {
  strncpy(token, input+i, TOKEN_SIZE);
   tokenが表に載ってなかったら、count=1で追加
   載っていたらcount+1
  }
 }

こんだけっしょ?



この投稿にコメントする

削除パスワード

No.25895

Re:連続する文字の出現頻度
投稿者---スケイス(2006/01/31 23:34:13)


    token[TOKEN_SIZE] = '\0';
    while(fgets(input, 256, fp) != NULL)
    {
        len = strlen(input) - TOKEN_SIZE;
        for ( i = 0; i <= len; ++i )
        {
            strncpy(token, input+i, TOKEN_SIZE);
            find=0;
            for(i = 0; i < table_size; i++)
            {
                if (strcmp(token, word_table[i].word) == 0)
                {
                    word_table[i].count++;
                    find = 1;
                    break;
                }
            }
                if (find == 0)
                {
                    word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                    strcpy(word_table[table_size].word,token);
                    word_table[table_size].count = 1;
                    table_size++;
                }
        }
    }


strncpy(token, input+i, TOKEN_SIZE);
   tokenが表に載ってなかったら、count=1で追加
   載っていたらcount+1
  }

ここをどう実現したらいいのかが分かりません。
テーブルになかったら+1してテーブルにあったらそのまま1ずつ加算していけばいいのですが、ここのif条件が分かりません。επιστημη様、考え方的には、単語と一緒のように考えていいのでしょうか?


この投稿にコメントする

削除パスワード

No.25896

Re:連続する文字の出現頻度
投稿者---nop(2006/02/01 00:26:06)


> strncpy(token, input+i, TOKEN_SIZE);
> tokenが表に載ってなかったら、count=1で追加
> 載っていたらcount+1
> ここをどう実現したらいいのかが分かりません。

「tokenが表に載っている」と言う事を調査するとき、
あなた自身が行うとすると、どの様な手順で行いますか?

日本語で細かく手順を考えてみて下さい。


# No.25849 の私の発言が生かされていないのは何故ですか?
#
# 日本語をCに翻訳できない時は、大抵は元の日本語がおおざっぱなときです。
# そのおおざっぱな日本語を細分化して行くことで、
# Cに翻訳できる様になってきます。
# まずは、日本語で徹底的に考えてみて下さい。


この投稿にコメントする

削除パスワード

No.25897

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 00:45:20)


>「tokenが表に載っている」と言う事を調査するとき、
>あなた自身が行うとすると、どの様な手順で行いますか?
tokenに3文字(例_th)が入っていて、テーブルにこの_thがない場合は、countの初期値を1にする。次にテーブルに_thがある場合はそのままcount++(conunt=count+1 このときcount=1)して、2、3,4・・・と加算していく。テーブルにあるかないかは、flagなどをつけ、flagがたったらそのまま加算、flagがたたなかったならばcount初期値を1していく。
私が行うとこんな感じになります。
nop様の意見は分かりますが、プログラムにできないアルゴリズムを日本語で説明するのが私にはできないからです。気に触るようでしたらあやまります。どうもすいませんでした。


この投稿にコメントする

削除パスワード

No.25898

Re:連続する文字の出現頻度
投稿者---RAPT(2006/02/01 01:27:20)


> プログラムにできないアルゴリズムを日本語で説明するのが
> 私にはできないからです。
順番が逆では?

母国語で、すべき手順(=アルゴリズム)を考え、
それをコードに起こすのです。



この投稿にコメントする

削除パスワード

No.25899

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 02:00:08)


ありがとうございます。日本語で理解したのならば、コードに起こすことは簡単なのでしょうか?私はC言語を始めて1年なんですが、文字操作と配列とポインタを完全に理解していません。普通の方はアルゴリズムを考えたらコードに起こすことはそんなに容易なことなんでしょうか?


この投稿にコメントする

削除パスワード

No.25902

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 04:40:21)


> 普通の方はアルゴリズムを考えたらコードに起こすことはそんなに容易なことなんでしょうか?

算数の文章問題から数式を起こすのと同じです。
文章問題が正確に/もれなく/丁寧に書かれているほど、
ほとんどそのまま数式に対応させることができます。



この投稿にコメントする

削除パスワード

No.25901

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 04:36:22)


>tokenに3文字(例_th)が入っていて、テーブルにこの_thがない場合は、countの初期値を1にする。次にテーブルに_thがある場合はそのままcount++(conunt=count+1 このときcount=1)して、2、3,4・・・と加算していく。テーブルにあるかないかは、flagなどをつけ、flagがたったらそのまま加算、flagがたたなかったならばcount初期値を1していく。
>私が行うとこんな感じになります。

でしょ? つまり「strtokでやってたのと同じことをすればいい」のですよ。



この投稿にコメントする

削除パスワード

No.25921

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 18:23:28)


>でしょ? つまり「strtokでやってたのと同じことをすればいい」のですよ。
strtokではスペースや改行を指定できましたが、3文字という文字数の指定方法がわかりません。
strncpy(token, input+i, TOKEN_SIZE);
ここの間に、strtokでfor文を書けばいのかと思いますが、書き方がわかりません。どのように文字数を設定すればいいのでしょうか?
find = 0;

    token[TOKEN_SIZE] = '\0';
    //ファイルから一行、inputに読み込む
    while(fgets(input, 256, fp) != 0)
    {
            int len = strlen(input) - TOKEN_SIZE;
            for ( i = 0; i <= len; ++i )
            {
                //i だけずらして TOKEN_SIZE 文字分 token にコピー
                strncpy(token, input+i, TOKEN_SIZE);
                strtokで3文字ずつに分ける。
                find = 0;
                    //word_tableとの照合
                    for(i = 0; i < table_size; i++)
                    {
                        //一致する単語を見つけた場合
                        if (strcmp(token, word_table[i].word) == 0)
                        {
                            word_table[i].count++;
                            find = 1;
                            break;
                        }
                    }
                        //word_table中に一致する単語がなかった場合
                        if (find == 0)
                        {
                            word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                            strcpy(word_table[table_size].word,token);
                            word_table[table_size].count = 1;
                            table_size++;
                        }
            }
    }



この投稿にコメントする

削除パスワード

No.25924

Re:連続する文字の出現頻度
投稿者---kz3(2006/02/01 18:57:30)


>>でしょ? つまり「strtokでやってたのと同じことをすればいい」のですよ。
>strtokではスペースや改行を指定できましたが、3文字という文字数の指定方法がわかりません。
>strncpy(token, input+i, TOKEN_SIZE);
>ここの間に、strtokでfor文を書けばいのかと思いますが、書き方がわかりません。どのように文字数を設定すればいいのでしょうか?

No.25840
> strncpy(token, input+i, TOKEN_SIZE);
> この使い方はすごくいいですね。ものすごく参考になりました。

こう言ったのは理解したからではないのですか?
No.25825-επιστημηさんのコードを良く読んで理解してみてください。
人のコードを読むとき、一行一行(一文一文)コメントつけていますか?

それぞれの文には何かしら意味のあるコードです。
初心・初級のうちは人のソースに自分なりのコメントを付けるのが勉強になります。

No.25825のコードは関数の意味と引数の意味を調べればそれほど難しいものではありません。


#include <stdio.h> #include <string.h> #define TOKEN_SIZE 3 int main() { int i; // 何故 TOKEN_SIZE+1 なのか? char token[TOKEN_SIZE+1]; const char* input = "Do you like apple?"; // 何故最後に TOKEN_SIZE を引くのか? int len = strlen(input) - TOKEN_SIZE; // 何故インデックス TOKEN_SIZE にヌル文字を入れるのか? token[TOKEN_SIZE] = '\0'; // i <= len で input が示す領域の外を参照する恐れはないのか? // ないなら、それは何故か? for ( i = 0; i <= len; ++i ) { // ここは何をしているのか? strncpy(token, input+i, TOKEN_SIZE); printf("[%s]\n", token); } return 0; }





この投稿にコメントする

削除パスワード

No.25926

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 21:14:00)


>>でしょ? つまり「strtokでやってたのと同じことをすればいい」のですよ。
>strtokではスペースや改行を指定できましたが、3文字という文字数の指定方法がわかりません。
>strncpy(token, input+i, TOKEN_SIZE);
>ここの間に、strtokでfor文を書けばいのかと思いますが、書き方がわかりません。

いや、だから、tokenには3文字に切り分けたのがとっくにはいってんですけど。



この投稿にコメントする

削除パスワード

No.25928

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 22:03:05)


>いや、だから、tokenには3文字に切り分けたのがとっくにはいってんですけど。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 10000    //word_tableの大きさ
#define YUSEN_JYUNI 5     //優先順位
#define TOKEN_SIZE 3

    struct word_count{
    char *word;  //単語
    int count;    //頻度
    };

int main(int argc, char *argv[])
{
    FILE *fp;
    struct word_count word_table[TABLE_SIZE]; //単語と頻度を格納する配列
    char input[256],token[TOKEN_SIZE+1],*moji;
    int i,j,table_size,find,bangou;
    table_size = 0;

    //ファイル入力にエラーが生じた場合
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("file open error!!\n");
        exit(1);
    }
    
    token[TOKEN_SIZE] = '\0';
    //ファイルから一行、inputに読み込む
    while(fgets(input, 256, fp) != 0)
    {
            int len = strlen(input) - TOKEN_SIZE;
            for ( i = 0; i <= len; ++i )
            {
                //i だけずらして TOKEN_SIZE 文字分 token にコピー
                strncpy(token, input+i, TOKEN_SIZE);
                find = 0;
                    //word_tableとの照合
                    for(i = 0; i < table_size; i++)
                    {
                        //一致する単語を見つけた場合
                        if (strcmp(token, word_table[i].word) == 0)
                        {
                            word_table[i].count++;
                            find = 1;
                            break;
                        }
                    }
                        //word_table中に一致する単語がなかった場合
                        if (find == 0)
                        {
                            word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                            strcpy(word_table[table_size].word,token);
                            word_table[table_size].count = 1;
                            table_size++;
                        }
            }
    }
    fclose(fp);

    //出現頻度順にソート
    for(i = 0; i < table_size; i++)
    {
        for(j = table_size-1; j >= i; j--)
        {
            if(word_table[i].count < word_table[j].count)
            {
                moji = word_table[i].word;
                word_table[i].word = word_table[j].word;
                word_table[j].word = moji;
                bangou = word_table[i].count;
                word_table[i].count = word_table[j].count;
                word_table[j].count = bangou;
            }
        }
    }

    //word_tableを出力//
    for (i = 0; i < YUSEN_JYUNI && i < table_size; i++)
    {
        printf("%4d: [%s]\n", word_table[i].count , word_table[i].word);
    }

    return 0;
}



tokenに3文字入っていることはわかりました。つまり3文字のひとまとまりになっているってことですよね?上のプログラムに何がたらないのでしょうか?3文字入っているのならそのまま、テーブルにあるかないかを見てなかったら3文字をstrcpyでテーブルに入れてカウントを1して、もし同じ3文字のひとまとまりがみつかったのならば、tokenとテーブルをstrcmpで比較して、一緒だたらそのままカウントする見たくなっていると思うのですが、何がたらないのでしょうか?


この投稿にコメントする

削除パスワード

No.25934

Re:連続する文字の出現頻度
投稿者---ぽへぇ(2006/02/01 22:21:13)




> for ( i = 0; i <= len; ++i )
このiが

>//word_tableとの照合
>for(i = 0; i < table_size; i++)

ここで壊れることに気づかないのは何故?
だから「何度もトレースしろ」と書いたのに...



この投稿にコメントする

削除パスワード

No.25927

Re:連続する文字の出現頻度
投稿者---ぽへぇ(2006/02/01 21:15:09)



>strtokではスペースや改行を指定できましたが、3
>文字という文字数の指定方法がわかりません。
> strtokで3文字ずつに分ける。

strtokって何をする関数か理解して書いて(使って)いますか?

#時には捨てる(使わない)勇気も必要



この投稿にコメントする

削除パスワード

No.25931

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 22:09:48)


strtokはhttp://www9.plala.or.jp/sgwr-t/lib/strtok.htmlここの参考にしました。分解対象文字列と区切りたい文字を指定し、使用すると思います。



この投稿にコメントする

削除パスワード

No.25932

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 22:13:23)


>strtokはhttp://www9.plala.or.jp/sgwr-t/lib/strtok.htmlここの参考にしました。分解対象文字列と区切りたい文字を指定し、使用すると思います。

だから"3文字で切る"のには適さない。


この投稿にコメントする

削除パスワード

No.25906

Re:連続する文字の出現頻度
投稿者---nop(2006/02/01 09:14:13)


>プログラムにできないアルゴリズムを日本語で説明するのが私にはできないからです。

確かに、「プログラムにできないアルゴリズムを日本語で説明する」のは難しいでしょう。
しかし、私が言っている事は、そう言う事ではありません。
これでは、作業の順番が逆になってしまいます。

プログラミングというのは、まず母国語で処理内容を考える事から始まります。
この時、「プログラミング言語にするとどうなるか?」という事は考えません。

母国語で処理内容の詳細をじっくり考えた後、
その母国語の内容をプログラミング言語へと翻訳します。

今のあなたは、母国語で処理内容を検討せずに、
いきなりプログラミング言語へ翻訳仕様としているから判らないのです。
元となる処理内容が無いまま翻訳など出来ません。

なので、「日本語で細かく手順を考えてみて下さい」
と言っているのです。


# 個人的には、箇条書きして考えていく事をお勧めします。


この投稿にコメントする

削除パスワード

No.25903

Re:連続する文字の出現頻度
投稿者---ぽへぇ(2006/02/01 06:59:48)



No.25895で(自分自身で)ほとんど回答できている、
ということに気づいて欲しいな。

自分で示したコードを自分の意図とどう違うのか考えながら
何度も机上とデバッガで交互にトレースしてみてください。

どこが悪いのかが見えてくると思います。

難しく考えすぎてない?
(まぁわかんない時って、そんなもんですが)



この投稿にコメントする

削除パスワード

No.25929

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 22:06:03)


アドバイスありがとうございます。
nop様、箇条書きで書くように心がけます。

ぽへぇ様、どこが悪いのか見えてこないのです。悲しいことに。




この投稿にコメントする

削除パスワード

No.25940

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/01 23:36:12)


みなさまのおかげで何とか動くプログラムになりました。ありがとうございました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TABLE_SIZE 10000    //word_tableの大きさ
#define YUSEN_JYUNI 10   //優先順位
#define TOKEN_SIZE 3

    struct word_count{
    char *word;  //単語
    int count;    //頻度
    };

int main(int argc, char *argv[])
{
    FILE *fp;
    struct word_count word_table[TABLE_SIZE]; //単語と頻度を格納する配列
    char input[256],token[TOKEN_SIZE+1],*moji;
    int i,j,table_size,find,bangou,len;
    table_size = 0;

    //ファイル入力にエラーが生じた場合
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("file open error!!\n");
        exit(1);
    }
    
    token[TOKEN_SIZE] = '\0';
    //ファイルから一行、inputに読み込む
    while(fgets(input, 256, fp) != 0)
    {
            len = strlen(input) - TOKEN_SIZE;
            for ( i = 0; i <= len; i++ )
            {
                //i だけずらして TOKEN_SIZE 文字分 token にコピー
                strncpy(token, input+i, TOKEN_SIZE);
                find = 0;
                    //word_tableとの照合
                    for(i = 0; i < table_size; i++)
                    {
                        //一致する単語を見つけた場合
                        if (strcmp(token, word_table[i].word) == 0)
                        {
                            word_table[i].count++;
                            find = 1;
                            break;
                        }
                    }
                        //word_table中に一致する単語がなかった場合
                        if (find == 0)
                        {
                            word_table[table_size].word = malloc((strlen(token)+1)*sizeof(char));
                            strncpy(word_table[table_size].word,token,TOKEN_SIZE);
                            word_table[table_size].count = 1;
                            table_size++;
                        }
            }
    }
    fclose(fp);

    //出現頻度順にソート
    for(i = 0; i < table_size; i++)
    {
        for(j = table_size-1; j >= i; j--)
        {
            if(word_table[i].count < word_table[j].count)
            {
                moji = word_table[i].word;
                word_table[i].word = word_table[j].word;
                word_table[j].word = moji;
                bangou = word_table[i].count;
                word_table[i].count = word_table[j].count;
                word_table[j].count = bangou;
            }
        }
    }

    //word_tableを出力//
    for (i = 0; i < YUSEN_JYUNI && i < table_size; i++)
    {
        printf("%4d: [%s]\n", word_table[i].count , word_table[i].word);
    }

    return 0;
}

テキストにDo you like apple?を書いて実行した結果、

1: [Do ]
1: [o y]
1: [ yo]
1: [you]
1: [ou ]
1: [u l]
1: [ li]
1: [lik]
1: [ike]
1: [ke ]
1: [e a]
1: [ ap]
1: [app]
1: [ppl]
1: [ple]
1: [le?]
] 1: [e?
1: [?
]
以上のようになりました。プログラムに間違っている箇所や使い方がおかしい箇所があればご教授よろしくおねがいします。



この投稿にコメントする

削除パスワード

No.25941

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 23:47:46)


>テキストにDo you like apple?を書いて実行した結果、

デバッグのしかたを知らんのだなぁ…
そんなんじゃテスト・データにならんやないか。
せめて:

Do you like apple?
you like orange, don't you?

このくらいは食わさんと

>] 1: [e?
> 1: [?
>]

改行コードが残ったまんまやし。



この投稿にコメントする

削除パスワード

No.25943

Re:連続する文字の出現頻度
投稿者---επιστημη(2006/02/01 23:52:00)


>以上のようになりました。プログラムに間違っている箇所や使い方がおかしい箇所があればご教授よろしくおねがいします。

25934 読んでないし



この投稿にコメントする

削除パスワード

No.25944

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/02 00:00:28)


改行コードは含まないようにしてみます。iがここで初期化されてしまうのですね。テキスト内を2行にしましたら、動きませんでした。考えて見ます。




この投稿にコメントする

削除パスワード

No.25946

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/02 02:33:01)


    //ファイルから一行、inputに読み込む
    while(fgets(input, 256, fp) != 0)
    {
        //読み込んだ一行からTOKEN_SIZEを引きforの回数を決定する
        len = strlen(input) - TOKEN_SIZE;
        for ( i = 0; i <= len; i++ )
        {
            //i だけずらして TOKEN_SIZE 文字分 token にコピー
            strncpy(token, input+i, TOKEN_SIZE);
            find = 0;
            //word_tableとの照合
            for(i = len; i < table_size; i++)
            {


for(i = len; i &lt; table_size; i++)ここをこのようにすると
テキスト内に
Do_you
Do_you
Do_you
が書かれていると実行結果は
1:[Do_]
1:[Do_]
1:[Do_]
となってしまいます。

for(i = 0; i &lt; table_size; i++)ここをこのようにすると
テキスト内に一行のみだった場合、
Do_you

1:[Do_]
1:[o_y]
1:[_yo]
1:[you]
このように正常な答えを返してくれます。iは何からはじめてテーブルと照合させればいいのでしょうか?私は、0からテーブルと照合させていかなければならないと思うのですが、ここが0だと一行だけに文字が書いてあった場合のみしか対応できないのです。もしテキスト内が行でしたら、実行を押しても処理が止まらないのです。何度も何度もすみませんが、ご教授よろしくおねがいします。


この投稿にコメントする

削除パスワード

No.25947

Re:連続する文字の出現頻度
投稿者---kz3(2006/02/02 03:16:11)



>for(i = len; i < table_size; i++)ここをこのようにすると
>テキスト内に
>Do_you
>Do_you
>Do_you
>が書かれていると実行結果は
>1:[Do_]
>1:[Do_]
>1:[Do_]
>となってしまいます。

なぜそうなるか、分かったのですか?


>for(i = 0; i < table_size; i++)ここをこのようにすると
>テキスト内に一行のみだった場合、
>Do_you
>
>1:[Do_]
>1:[o_y]
>1:[_yo]
>1:[you]
>このように正常な答えを返してくれます。

同じ条件("Do you"が3行)で正常かどうかを考えてください。


>iは何からはじめてテーブルと照合させればいいのでしょうか?
>私は、0からテーブルと照合させていかなければならないと思うのですが、
>ここが0だと一行だけに文字が書いてあった場合のみしか対応できないのです。

複数行とかは関係ないですよ。
"Yo!Yo!"とか食わせたら2個目の"Yo!"でいつまで経っても終了しません。

単語を頻度でソートするとき二重ループでどのように書きましたか?
何故○○を□□用意するのか理解していないから今回のようなループを書いてしまうんですよ。


>ご教授よろしくおねがいします。
No.25934で言われている内容を理解していますか?





この投稿にコメントする

削除パスワード

No.25948

Re:連続する文字の出現頻度
投稿者---ぽへぇ(2006/02/02 03:22:34)


内側のループにiを使わない。

kz3さんにNo.25947で指摘されたことをよく考えてね。
一日考えて解らなかったくらいで聞くんじゃぁないよ。

#掲示板システムに甘えすぎのような気がしてきた。



この投稿にコメントする

削除パスワード

No.25949

Re:連続する文字の出現頻度
投稿者---スケイス(2006/02/02 04:25:12)


ぽへぇ様、kz3様、forの根本的な使い方が間違っていたのに気がつきました。上のforを、間違えないようにpとqにしました。本当だったらforの中で初期化を行っているのでiとjを使うべきなんでしょうが、あえて違う変数にしました。私自身がソースを見てわかるようにしました。色々と教えて下さったεπιστημη様、RAPT様、nop様本当にありがとうございました。





この投稿にコメントする

削除パスワード

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