ページ 11

C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月18日(木) 21:35
by 私のポート番号は53番です
学校の課題がわからないのでここで、質問させていただきます。
以下にベースとなるコードを表記しこのコードを習性して、C言語で文書中の文字の頻度を計算するプログラムを作成します。

コード:

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

int main(void) {
  int x;
  int count[128] = { 0 };

  x = getchar();
  while (x != EOF) {
    if (isgraph(x)) {
      count[x] += 1;
    }
    x = getchar();
  }

  for (x = 0; x < 128; x++) {
    if (count[x] != 0) {
      printf("%c %3d\n", x, count[x]);
    }
  }

  return 0;
}
コードの仕様を箇条書きすると、
1、標準入力よりASCII文字を読み込み、文字の頻度の降順に、頻度が同じならばASCII表の順にソートし,各行に「文字 頻度」の形式で出力
2、大文字と小文字を区別せずに頻度を計算
3、空白(SP)、改行(CR)、タブ(HT)の頻度は計算しない、図形文字以外の文字は頻度を計算しない
4、頻度情報の出力順は実行例と同じにします。特に頻度が0の文字を表示してはいけない
です。
コードの必須条件を箇条書きすると、
A.頻度情報を格納するために、構造体を必ず定義、構造体名、メンバ名およびデータ型は自由
B.その構造体を格納する配列をmain関数の局所変数として定義、配列のメモリ領域をmalloc関数で確保する必要無し
C.main関数以外に2個以上の関数を定義
D.文字の入力にはgetchar関数を使用
E. 文字種の判断はisupper関数などを使用
です。
テストデータの中身は、

#09=#@ahz
0099==hhzz
99h

です。このテストデータを用いて課題のコードを実行すると

9 5
h 4
0 3
= 3
z 3
# 2
@ 1
a 1

となります。
下記のURLにアスキー表へのリンクを張りました。
http://www9.plala.or.jp/sgwr-t/c_sub/ascii.html
自作したコードでは、構造体の宣言があいまいなので、頻度の値がおかしくなってしまいます。しかし、どこをどうなおせばいいのかわからないため、手のつけようがありません。ご協力お願い致します。以下に自作したコードを記します。

コード:

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

typedef struct asc2{
  char asc2char;
  int fre;
} ASC2;

int main(void) {
  ASC2 asc2[128];
  int i=0;
  asc2[0].asc2char = getchar();
  while (asc2[i].asc2char != EOF) {
    if (isgraph(asc2[i].asc2char)) {
      asc2[i].fre += 1;
    }
    asc2[i].asc2char = getchar();
    i++;
  }

  for (i = 0; i < 10; i++) {
    if (asc2[i].fre != 0) {
      printf("%c %3d\n", asc2[i].asc2char, asc2[i].fre);
    }
  }

  return 0;
}
よろしくお願いいたします。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月18日(木) 21:46
by box
私のポート番号は53番です さんが書きました: 自作したコードでは、構造体の宣言があいまいなので、頻度の値がおかしくなってしまいます。
宣言があいまい(ちょっと意味不明ですが)だからではなく、頻度の値をゼロで初期化していないからでありましょう。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月18日(木) 22:25
by みけCAT
box さんが書きました:
私のポート番号は53番です さんが書きました: 自作したコードでは、構造体の宣言があいまいなので、頻度の値がおかしくなってしまいます。
宣言があいまい(ちょっと意味不明ですが)だからではなく、頻度の値をゼロで初期化していないからでありましょう。
初期化していないだけでなく、元のコードで頻度の計算をしていた部分に書かれているコードもデタラメですね。

テストデータが短いからいいですが、テストデータが128バイトを超えると配列の範囲外にアクセスしてしまいますね。
また、2回目以降に13行目に来たとき、asc2.asc2charの値は意味が無いかもしれません。
私のポート番号は53番です さんが書きました:テストデータの中身は、

#09=#@ahz
0099==hhzz
99h

です。

他のテストケースに対応させる必要は無いのですか?

私のポート番号は53番です さんが書きました:しかし、どこをどうなおせばいいのかわからないため、手のつけようがありません。ご協力お願い致します。

全体的におかしいので、なおす(修正する)というより最初(に提示されたコード)からやりなおすのが良さそうだと思います。

コード:

/* include OK */
#include <stdio.h>
#include <ctype.h>

/* 構造体の定義はOK (asc2charという変数名の意味はよくわからないが、問題なし) */
typedef struct asc2{
  char asc2char;
  int fre;
} ASC2;

/* main関数の型は正しい、OK */
int main(void) {
  /* 配列とループカウンタはOK */
  ASC2 asc2[128];
  int i=0;
  asc2[0].asc2char = getchar(); /* NG なぜそこに読み込む? */
  while (asc2[i].asc2char != EOF) { /* NG 意味のない(未初期化)データの比較、範囲外アクセスのリスク? */
    if (isgraph(asc2[i].asc2char)) { /* NG 範囲外アクセスのリスク、未定義動作(asc2[i].asc2charがEOFでない負の場合)のリスク? */
      asc2[i].fre += 1;
    }
    asc2[i].asc2char = getchar(); /* NG 範囲外アクセスのリスク */
    i++; /* そもそもここでiをインクリメントする必要は無いのでは? */
  }

  /* NG ソートする処理がない */

  for (i = 0; i < 10; i++) { /* NG? ループの回数が適当 */
    if (asc2[i].fre != 0) { /* OK */
      printf("%c %3d\n", asc2[i].asc2char, asc2[i].fre); /* OK? 提示された出力で@の所だけスペースが少ないのは入力ミス? */
    }
  }

  return 0; /* OK */
}
私のポート番号は53番です さんが書きました:C.main関数以外に2個以上の関数を定義
とりあえず自明な方法でこれを満たしておきましょう。定義するだけで使用する必要は無いのですね。

コード:

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

/* main関数以外に2個以上の関数を定義 */
void kansuu1(void) {}
void kansuu2(void) {}

typedef struct asc2{
  char asc2char;
  int fre;
} ASC2;

int main(void) {
  ASC2 asc2[128];
  int i=0;
  asc2[0].asc2char = getchar();
  while (asc2[i].asc2char != EOF) {
    if (isgraph(asc2[i].asc2char)) {
      asc2[i].fre += 1;
    }
    asc2[i].asc2char = getchar();
    i++;
  }

  for (i = 0; i < 10; i++) {
    if (asc2[i].fre != 0) {
      printf("%c %3d\n", asc2[i].asc2char, asc2[i].fre);
    }
  }

  return 0;
}

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 12:55
by 私のポート番号は53番です
boxさん、みけcatさんご指摘ありがとうございます。
みけcatさんのおっしゃるとうり元のコードから作り直します。

その前に問題の構造体の初期化のために以下のサイト
http://www.isl.ne.jp/pcsp/beginC/C_Language_14.html

の例題1構造体を作ろうを参考にして作成したコードが

コード:

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

typedef struct asc2{
  char mozi;
  int fre;
  int tenfig;
} ASC2;

int main(void) {
  ASC2 array[94] =
    {
      {"!",0,33}
      {"""",0,34}
      {"#",0,35}
      {"$",0,36}
      {"%",0,37}
      {"'",0,38}
      {"(",0,40}
      {")",0,41}
      {"*",0,42}
      {"+",0,43}
      {",",0,44}
      {"-",0,45}
      {".",0,46}
      {"/",0,47}
      {"0",0,48}
      {"1",0,49}
      {"2",0,50}
      {"3",0,51}
      {"4",0,52}
      {"5",0,53}
      {"6",0,54}
      {"7",0,55}
      {"8",0,56}
      {"9",0,57}
      {":",0,58}
      {";",0,59}
      {"<",0,60}
      {"=",0,61}
      {">",0,62}
      {"?",0,63}
      {"@",0,64}
      {"A",0,65}
      {"B",0,66}
      {"C",0,67}
      {"D",0,68}
      {"E",0,69}
      {"F",0,70}
      {"G",0,71}
      {"H",0,72}
      {"I",0,73}
      {"J",0,74}
      {"K",0,75}
      {"L",0,76}
      {"M",0,77}
      {"N",0,78}
      {"O",0,79}
      {"P",0,80}
      {"Q",0,81}
      {"R",0,82}
      {"S",0,83}
      {"T",0,84}
      {"U",0,85}
      {"V",0,86}
      {"W",0,87}
      {"X",0,88}
      {"Y",0,89}
      {"Z",0,90}
      {"[",0,91}
      {"\\",0,92}
      {"]",0,93}
      {"^",0,94}
      {"_",0,95}
      {"`",0,96}
      {"a",0,65}
      {"b",0,66}
      {"c",0,67}
      {"d",0,68}
      {"e",0,69}
      {"f",0,70}
      {"g",0,71}
      {"h",0,72}
      {"i",0,73}
      {"j",0,74}
      {"k",0,75}
      {"l",0,76}
      {"m",0,77}
      {"n",0,78}
      {"o",0,79}
      {"p",0,80}
      {"q",0,81}
      {"r",0,82}
      {"s",0,83}
      {"t",0,84}
      {"u",0,85}
      {"v",0,86}
      {"w",0,87}
      {"x",0,88}
      {"y",0,89}
      {"z",0,90}
      {"{",0,123}
      {"|",0,124}
      {"}",0,125}
      {"~",0,126}	
    };
  int i=0;

 array[0].mozi = getchar();
  while (array[i].mozi != EOF) {
    if (isgraph(array[i].mozi)) {
      array[i].fre += 1;
    }
    array[i].mozi = getchar();
    i++;
  }

  for (i = 0; i < 94; i++) {
    if (array[i].fre != 0) {
      printf("%c %3d\n", array[i].mozi, array[i].fre);
    }
  }

  return 0;
}
です。
しかし、このコードで、ubuntuの端末でcc -oコマンドでコンパイルすると、

関数 ' main' 内:
13: 7: エラー: 初期化でポインタからキャスト無しに整数を作成しています
13: 7: エラー: (' array[0].mozi' 用の初期化付近)
13: 7: エラー: 初期化子の要素がロード時に計算出来ません
14: 7: エラー: expected ' }' before '{' token
となってうまく実行できません。
13行目のどの箇所を修正すればよいでしょうか。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 13:37
by みけCAT
私のポート番号は53番です さんが書きました:13行目のどの箇所を修正すればよいでしょうか。
"の代わりに'を使い、最後に,を追加してください。
13~105行目のうち、以下の行以外も同様に修正してください。
* 14行目: {'\"',0,34}, としてください。
* 18行目: {'\'',0,38}, としてください。
* 105行目: {'~',0,126} としてください。

※テストしていません

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 19:57
by 私のポート番号は53番です
みけcatさん返答ありがとうございます。
無事、構造体の初期化に成功しました。
みけcat さんが書きました: 他のテストケースに対応させる必要は無いのですか?
ですがおっしゃる通り他のテストデータも必要です。

以下のコードは
わたしが提示した

9 5
h 4
0 3
= 3
z 3
# 2
@ 1
a 1

は出力できました。

コード:

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



/*構造体の宣言*/
typedef struct asc2{
  char mozi;
  int fre;
  int tenfig;
  int id;
} ASC2;

/*重複した頻度をid順にソート*/
void sort3(ASC2 a[]) {
  /*ループカウンタ*/
  int i,j;
  /*避難所*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*文字が頻度が一致していてかつ10進数番号が同じなら入れ替え*/
      if(a[i].fre==a[j].fre){
	if(a[i].tenfig==a[j].tenfig){
	  /*id順で場所の入れ替え*/
	  if(a[i].id>a[j].id){
	    /*スワップ*/
	    dumy=a[i];
	    a[i].id = a[j].id;
	    a[j]=dumy;
	  }
	}	
      }
    }
  }
}
/*頻度が同じときの並びの処理*/
void sort2(ASC2 a[], int i, int j) {
  /*避難*/
  ASC2 tmp;
  /*id順でスワップ*/
  if(a[i].id>a[j].id){
    tmp=a[i];
    a[i]=a[j];
    a[j]=tmp;
  }
}
/*sortした後に再ソートして順番を直す*/
void sort4(ASC2 a[]){
  /*ループカウンタ*/
  int i,j;
  /*避難所*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*頻度を比較*/
      if(a[i].fre <a[j].fre){
	/*頻度が高い順にスワップ*/
	dumy = a[i];
	a[i] = a[j];
	a[j] = dumy;
      }
    }
    /*頻度が同じなら、idで順番を決める*/
    if(a[i].fre==a[j].fre){
      sort2(a,i,j);
    }
  }
}
/*ソート*/
void sort(ASC2 a[]) {
  /*ループカウンタ*/
  int i,j;
  /*避難*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*頻度の大小比較*/
      if(a[i].fre <a[j].fre){
	/*頻度の高い順にスワップ*/
	dumy = a[i];
	a[i] = a[j];
	a[j] = dumy;
      }/*頻度が一緒ならidで比較*/
      if(a[i].fre==a[j].fre){
	sort2(a,i,j);
      }
      /*10進数が一緒なら同じ文字なので頻度を共有*/
      if(a[i].tenfig==a[j].tenfig){
	a[i].fre+=a[j].fre;
	a[j].fre=a[i].fre;
      }
      
    }
  }
  
}





int main(void) {
  /*構造体の宣言*/
  ASC2 array[93] =
    {
      {'!',0,33,0},
      {'\"',0,34,1},
      {'#',0,35,2},
      {'$',0,36,3},
      {'%',0,37,4},
      {'\'',0,38,5},
      {'(',0,40,6},
      {')',0,41,7},
      {'*',0,42,8},
      {'+',0,43,9},
      {',',0,44,10},
      {'-',0,45,11},
      {'.',0,46,12},
      {'/',0,47,13},
      {'0',0,48,14},
      {'1',0,49,15},
      {'2',0,50,16},
      {'3',0,51,17},
      {'4',0,52,18},
      {'5',0,53,19},
      {'6',0,54,20},
      {'7',0,55,21},
      {'8',0,56,22},
      {'9',0,57,23},
      {':',0,58,24},
      {';',0,59,25},
      {'<',0,60,26},
      {'=',0,61,27},
      {'>',0,62,28},
      {'?',0,63,29},
      {'@',0,64,30},
      {'A',0,65,31},
      {'B',0,66,32},
      {'C',0,67,33},
      {'D',0,68,34},
      {'E',0,69,35},
      {'F',0,70,36},
      {'G',0,71,37},
      {'H',0,72,38},
      {'I',0,73,39},
      {'J',0,74,40},
      {'K',0,75,41},
      {'L',0,76,42},
      {'M',0,77,43},
      {'N',0,78,44},
      {'O',0,79,45},
      {'P',0,80,46},
      {'Q',0,81,47},
      {'R',0,82,48},
      {'S',0,83,49},
      {'T',0,84,50},
      {'U',0,85,51},
      {'V',0,86,52},
      {'W',0,87,53},
      {'X',0,88,54},
      {'Y',0,89,55},
      {'Z',0,90,56},
      {'[',0,91,57},
      {'\\',0,92,58},
      {']',0,93,59},
      {'^',0,94,60},
      {'_',0,95,61},
      {'`',0,96,62},
      {'a',0,65,63},
      {'b',0,66,64},
      {'c',0,67,65},
      {'d',0,68,66},
      {'e',0,69,67},
      {'f',0,70,68},
      {'g',0,71,69},
      {'h',0,72,70},
      {'i',0,73,71},
      {'j',0,74,72},
      {'k',0,75,73},
      {'l',0,76,74},
      {'m',0,77,75},
      {'n',0,78,76},
      {'o',0,79,77},
      {'p',0,80,78},
      {'q',0,81,79},
      {'r',0,82,80},
      {'s',0,83,81},
      {'t',0,84,82},
      {'u',0,85,83},
      {'v',0,86,84},
      {'w',0,87,85},
      {'x',0,88,86},
      {'y',0,89,87},
      {'z',0,90,88},
      {'{',0,123,89},
      {'|',0,124,90},
      {'}',0,125,91},
      {'~',0,126,92},	
    };
  /*ループカウンタ*/
  int i=0;
  /*入力文字受け取り*/
  char x;

  
  
  /*ファイルの最後まで呼び出し*/
  while ((x=getchar()) != EOF) {
    /*登録した文字とxを比較*/
    for(i=0;i<93;i++){
      /*一致したら頻度+1*/
      if(x==array[i].mozi){
	array[i].fre +=1; 
      }
    }
  }
  /*ソート処理*/
      sort(array);
/*重複した頻度をid順にソート*/
      sort3(array);
      /*sort3で乱れた順番を再ソート*/
      sort4(array);
      /*頻度0以外出力*/
  for (i = 0; i < 93; i++) {
    if (array[i].fre != 0) {
      printf("%c %3d\n", array[i].mozi, array[i].fre);
    }
  }
  
  return 0;
}
しかし、他のテストデータ

00123456789
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

などのアルファベットが二回登場する時の場合の出力が

0 2
A 2
a 2
B 2
b 2
C 2
c 2
D 2
d 2
E 2
e 2
F 2
f 2
G 2
g 2
H 2
h 2
I 2
i 2
J 2
j 2
K 2
k 2
L 2
l 2
M 2
m 2
N 2
n 2
O 2
o 2
P 2
p 2
Q 2
q 2
R 2
r 2
S 2
s 2
T 2
t 2
U 2
u 2
V 2
v 2
W 2
w 2
X 2
x 2
Y 2
y 2
Z 2
z 2
9 1
: 1
; 1
< 1
= 1
> 1
? 1
@ 1
! 1
" 1
# 1
$ 1
% 1
' 1
( 1
) 1
* 1
+ 1
, 1
- 1
. 1
/ 1
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
[ 1
\ 1
] 1
^ 1
_ 1
` 1
{ 1
| 1
} 1
~ 1

アルファベットが固まって表示され、しかもアルファベット以降の文字もバラバラに並べられます。

0 2
A 2
B 2
C 2
D 2
E 2
F 2
G 2
(省略)
a 2
b 2
c 2
d 2
e 2
f 2
g 2
(省略)
! 1
" 1
# 1
$ 1
% 1
(省略)
と表示させるには、どのようにソートすればよいでしょうか?またsort関数内で別途配列が必要ですか?

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 21:15
by 私のポート番号は53番です
sort5関数を使って改良を加えましたが、アルファベットを分離出来ませんでした。
分離の方法はどうすればよろしいでしょうか?

A
a
B
b
C
c
D
d
E
e
(省略)
ではなく
A
B
C
D
E
(省略)と表示させるにはどうすればよいでしょうか?

以下にコードを記します。

コード:

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



/*構造体の宣言*/
typedef struct asc2{
  char mozi;
  int fre;
  int tenfig;
  int id;
} ASC2;

/*重複した頻度をid順にソート*/
void sort3(ASC2 a[]) {
  /*ループカウンタ*/
  int i,j;
  /*避難所*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*文字が頻度が一致していてかつ10進数番号が同じなら入れ替え*/
      if(a[i].fre==a[j].fre){
	if(a[i].tenfig==a[j].tenfig){
	  /*id順で場所の入れ替え*/
	  if(a[i].id>a[j].id){
	    /*スワップ*/
	    dumy=a[i];
	    a[i].id = a[j].id;
	    a[j]=dumy;
	  }
	}	
      }
    }
  }
}
/*頻度が同じときの並びの処理*/
void sort2(ASC2 a[], int i, int j) {
  /*避難*/
  ASC2 tmp;
  /*id順でスワップ*/
  if(a[i].id>a[j].id){
    tmp=a[i];
    a[i]=a[j];
    a[j]=tmp;
  }
}
/*sortした後に再ソートして順番を直す*/
void sort4(ASC2 a[]){
  /*ループカウンタ*/
  int i,j;
  /*避難所*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*頻度を比較*/
      if(a[i].fre <a[j].fre){
	/*頻度が高い順にスワップ*/
	dumy = a[i];
	a[i] = a[j];
	a[j] = dumy;
      }
    }
    /*頻度が同じなら、idで順番を決める*/
    if(a[i].fre==a[j].fre){
      sort2(a,i,j);
    }
  }
}
/*ソート*/
void sort(ASC2 a[]) {
  /*ループカウンタ*/
  int i,j;
  /*避難*/
  ASC2 dumy;
  /*配列を回す*/
  for(i = 0; i < 93; i++){
    for(j = i + 1; j < 93; j++){
      /*頻度の大小比較*/
      if(a[i].fre <a[j].fre){
	/*頻度の高い順にスワップ*/
	dumy = a[i];
	a[i] = a[j];
	a[j] = dumy;
      }/*頻度が一緒ならidで比較*/
      if(a[i].fre==a[j].fre){
	sort2(a,i,j);
      }
      /*10進数が一緒なら同じ文字なので頻度を共有*/
      if(a[i].tenfig==a[j].tenfig){
	a[i].fre+=a[j].fre;
	a[j].fre=a[i].fre;
      }
      
    }
  }
  
}
void sort5(ASC2 a[]){
  /*ループカウンタ*/
  int j,c=0;
  /*避難*/
  ASC2 dumy;
  /*配列を回す*/
  for(j = 0; j < 93; j++){
    /*10進数で同一のアルファベットを比較*/
    if(a[j].tenfig==a[j+1].tenfig){
      /*id56以降の文字と交換のためにcで移動*/
      while(a[j+c].id <= 56){
	c++;
      }
      dumy=a[j+c];
      a[j+c+30]=a[j+1];
      a[j+1]=dumy;
      c=0;
    }
  }
}
int main(void) {
  /*構造体の宣言*/
  ASC2 array[93] =
    {
      {'!',0,33,0},
      {'\"',0,34,1},
      {'#',0,35,2},
      {'$',0,36,3},
      {'%',0,37,4},
      {'\'',0,38,5},
      {'(',0,40,6},
      {')',0,41,7},
      {'*',0,42,8},
      {'+',0,43,9},
      {',',0,44,10},
      {'-',0,45,11},
      {'.',0,46,12},
      {'/',0,47,13},
      {'0',0,48,14},
      {'1',0,49,15},
      {'2',0,50,16},
      {'3',0,51,17},
      {'4',0,52,18},
      {'5',0,53,19},
      {'6',0,54,20},
      {'7',0,55,21},
      {'8',0,56,22},
      {'9',0,57,23},
      {':',0,58,24},
      {';',0,59,25},
      {'<',0,60,26},
      {'=',0,61,27},
      {'>',0,62,28},
      {'?',0,63,29},
      {'@',0,64,30},
      {'A',0,65,31},
      {'B',0,66,32},
      {'C',0,67,33},
      {'D',0,68,34},
      {'E',0,69,35},
      {'F',0,70,36},
      {'G',0,71,37},
      {'H',0,72,38},
      {'I',0,73,39},
      {'J',0,74,40},
      {'K',0,75,41},
      {'L',0,76,42},
      {'M',0,77,43},
      {'N',0,78,44},
      {'O',0,79,45},
      {'P',0,80,46},
      {'Q',0,81,47},
      {'R',0,82,48},
      {'S',0,83,49},
      {'T',0,84,50},
      {'U',0,85,51},
      {'V',0,86,52},
      {'W',0,87,53},
      {'X',0,88,54},
      {'Y',0,89,55},
      {'Z',0,90,56},
      {'[',0,91,57},
      {'\\',0,92,58},
      {']',0,93,59},
      {'^',0,94,60},
      {'_',0,95,61},
      {'`',0,96,62},
      {'a',0,65,63},
      {'b',0,66,64},
      {'c',0,67,65},
      {'d',0,68,66},
      {'e',0,69,67},
      {'f',0,70,68},
      {'g',0,71,69},
      {'h',0,72,70},
      {'i',0,73,71},
      {'j',0,74,72},
      {'k',0,75,73},
      {'l',0,76,74},
      {'m',0,77,75},
      {'n',0,78,76},
      {'o',0,79,77},
      {'p',0,80,78},
      {'q',0,81,79},
      {'r',0,82,80},
      {'s',0,83,81},
      {'t',0,84,82},
      {'u',0,85,83},
      {'v',0,86,84},
      {'w',0,87,85},
      {'x',0,88,86},
      {'y',0,89,87},
      {'z',0,90,88},
      {'{',0,123,89},
      {'|',0,124,90},
      {'}',0,125,91},
      {'~',0,126,92},	
    };
  /*ループカウンタ*/
  int i=0;
  /*入力文字受け取り*/
  char x;

  
  
  /*ファイルの最後まで呼び出し*/
  while ((x=getchar()) != EOF) {
    /*登録した文字とxを比較*/
    for(i=0;i<93;i++){
      /*一致したら頻度+1*/
      if(x==array[i].mozi){
	array[i].fre +=1; 
      }
    }
  }
  /*ソート処理*/
      sort(array);
/*重複した頻度をid順にソート*/
      sort3(array);
      /*sort3で乱れた順番を再ソート*/
      sort4(array);
      /*頻度0以外出力*/
      sort5(array);
  for (i = 0; i < 93; i++) {
    if (array[i].fre != 0) {
      printf("%c %3d\n", array[i].mozi, array[i].fre);
    }
  }
  
  return 0;
}

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 22:28
by みけCAT
私のポート番号は53番です さんが書きました:sort5関数を使って改良を加えましたが、アルファベットを分離出来ませんでした。
分離の方法はどうすればよろしいでしょうか?

A
a
B
b
C
c
D
d
E
e
(省略)
ではなく
A
B
C
D
E
(省略)と表示させるにはどうすればよいでしょうか?
うーん、難しそうですね。
「アルファベットを分離」とは具体的にどういうことでしょうか?
私のポート番号は53番です さんが書きました:

コード:

  /*ソート処理*/
      sort(array);
/*重複した頻度をid順にソート*/
      sort3(array);
      /*sort3で乱れた順番を再ソート*/
      sort4(array);
      /*頻度0以外出力*/
      sort5(array);
「ソート」を名乗る処理を連続して何度もかけている時点で怪しい(コードの臭いだ)と思います。
整理するべきでしょう。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月19日(金) 22:31
by みけCAT
自分で実装してみたコードを置いておきます。
► スポイラーを表示

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月20日(土) 16:03
by 私のポート番号は53番です。
みけcatさん返信ありがとうございます。
ソートの整理をしてみます。

話は変わるのですが、c言語の課題は普段学校のOSがubuntuのPCを使っているので、自宅のOSがwindowsなので、利用する環境と異なっています。
自宅で課題をやるために、以下のサイト「学習用C言語開発環境 Ver 0.0.9.0 」
http://9cguide.appspot.com/p_9cide.html
のEasyIDECという初学者向けのコンパイラ兼テキストエディタをインストールして使用としたのですが、getchar関数を使うため、プログラムを実行するとコマンドプロンプト画面が表示されて、
ファイル読み込みをしなければいけないのですが、

#09=#@ahz
0099==hhzz
99h

などのテストデータはどのように読み込ませればよいでしょうか?
学校のubuntuだと、うろ覚えですが、
test.exe > testdata1.dat
なかんじで端末に読み込ませていました。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月20日(土) 16:11
by 私のポート番号は53番です。
すみません。No.8のコメントを見ていませんでした。
[quote="みけcat"]自分で実装してみたコードを置いておきます。[/quote]

みけcatさん、コーディングしていただきありがとうございます。
早速実装してみます。

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月20日(土) 21:39
by みけCAT
私のポート番号は53番です。 さんが書きました:EasyIDECという初学者向けのコンパイラ兼テキストエディタをインストールして使用としたのですが、getchar関数を使うため、プログラムを実行するとコマンドプロンプト画面が表示されて、
ファイル読み込みをしなければいけないのですが、

#09=#@ahz
0099==hhzz
99h

などのテストデータはどのように読み込ませればよいでしょうか?
1. コマンドプロンプトを開く
2. cdコマンドでプロジェクトのディレクトリ(「プロジェクト」タブで確認できる)に移動する
3. 「(プロジェクト名).exe < (テストデータのファイルのパス)」というコマンドを実行する

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月21日(日) 14:14
by 私のポート番号は53番です。
みけcatさん返信ありがとうございます。
みけcat さんが書きました:1. コマンドプロンプトを開く
2. cdコマンドでプロジェクトのディレクトリ(「プロジェクト」タブで確認できる)に移動する
3. 「(プロジェクト名).exe < (テストデータのファイルのパス)」というコマンドを実行する
なのですが、3の「(プロジェクト名).exe < (テストデータのファイルのパス)」というコマンドを実行なのですが、入力しても、

アクセスが拒否されました。

以下のサイトの「コマンドを実行するとアクセスが拒否される」
http://pasofaq.jp/windows/command/accessdeny.htm

の方法で、コマンドプロンプトを管理者として実行したのですが、

同じく

アクセスが拒否されました。

とでました。

ディレクトリの位置は「プロジェクト」タブで確認できるディレクトリの位置に移動しました。
また、プロジェクト名は、testで、
3のコマンドは

test.exe < c:Users\(ユーザ名\AppData\Local\EasyIDEC\project\test\test

にしました。ファイルのパスは2で移動したディレクトリと同じです。このディレクトリにはしっかりテストデータも入れました。

何をどうすればアクセスできるようになるでしょうか?

Re: C言語で文書中の文字の頻度を計算するプログラムを作成したい

Posted: 2015年6月25日(木) 17:16
by 私のポート番号は53番です
► スポイラーを表示
みけcatさんから頂いたコードを参考にして、自分なりにコードを完成させました。
多大なご助力ありがとうございました。
► スポイラーを表示