回答編集履歴
2
'z' の値がタイポ
answer
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
前提となる[アスキーコード表](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)を確認すると
|
7
7
|
'a' == 0x61 == 97
|
8
|
-
'z' == 0x7a ==
|
8
|
+
'z' == 0x7a == 122 です。
|
9
9
|
アルファベットは 'a' ~ 'z' の26文字あるので、出現回数を保持する配列の要素数は26必要です。したがって int c[26]; としたい。
|
10
10
|
|
11
11
|
そのうえで、例えば'a' の出現回数を c['a'] とでもしたいところですが、それだと c[97] となってしまってダメ。そこで
|
@@ -22,7 +22,7 @@
|
|
22
22
|
int c[INDEX('z' + 1)] = {0};
|
23
23
|
|
24
24
|
ここは、要素数26の配列を定義して(メモリを割り当てて)、その全ての要素を0で初期化しています。
|
25
|
-
- INDEX('z'+1) => 'z' + 1 - 'a' =>
|
25
|
+
- INDEX('z'+1) => 'z' + 1 - 'a' => 122 + 1 - 97 => 26 であるから、
|
26
26
|
int c[INDEX('z' + 1)] は int c[26] と展開される。めでたしめでたし(アルファベットが26文字であることは常識の範疇だから最初から int c[26] = {0}; としても構わないと思う)。
|
27
27
|
- int c[INDEX('z'+1)]; としただけだと、メモリは割当られるが、値は不定になってしまう。各文字の出現回数を数えるには、最初の値をすべてを0にしておく(0に初期化する)必要がある。
|
28
28
|
- 「= {0}」 の部分で配列の全ての値を0で初期化する。ここに「0」は一個しか書かれていないので c[0] = 0 だけが初期化されるかと思うと、さにあらず。初期値の指定がある場合、初期値が省略された c[1] ~ c[25] も初期値を0にするという約束なので。
|
1
説明を補足修正
answer
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
int main(int argc, char *argv[]) {
|
2
|
-
main()関数、戻り値の型と引数の型を示している…程度でよさそうですね。
|
2
|
+
main()関数の冒頭部分で、戻り値の型と引数の型を示している…程度でよさそうですね。
|
3
3
|
|
4
4
|
``` #define INDEX(x) (x-'a') ```
|
5
|
+
|
6
|
+
前提となる[アスキーコード表](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)を確認すると
|
5
7
|
'a' == 0x61 == 97
|
6
8
|
'z' == 0x7a == 112 です。
|
7
|
-
アルファベット 'a' ~ 'z' の26文字あるので、出現回数を保持する配列の要素数は26必要です。したがって
|
9
|
+
アルファベットは 'a' ~ 'z' の26文字あるので、出現回数を保持する配列の要素数は26必要です。したがって int c[26]; としたい。
|
8
|
-
int c[26]; としたい。
|
9
10
|
|
10
|
-
そのうえで、例えば'a' の出現回数を c['a']
|
11
|
+
そのうえで、例えば'a' の出現回数を c['a'] とでもしたいところですが、それだと c[97] となってしまってダメ。そこで
|
11
|
-
'a' => 0
|
12
|
+
'a' => 0 (== 'a' - 'a')
|
12
|
-
'b' => 1
|
13
|
+
'b' => 1 (== 'b' - 'a')
|
13
14
|
:
|
14
|
-
'z' => 25
|
15
|
+
'z' => 25 (== 'z' - 'a')
|
16
|
+
と変換するマクロ INDEX(x) を作ればよい。見ての通り、INDEX(x) マクロは (x - 'a') を計算すれば良いことがわかる。
|
15
|
-
|
17
|
+
INDEX(x) マクロを作れば
|
16
|
-
c[INDEX(tolower(ch))]++
|
18
|
+
c[INDEX(tolower(ch))]++
|
17
19
|
はchの値が文字コード('a' なら97)のまま、その文字の出現回数を+1できます。
|
20
|
+
念のため:tolower(ch) は、ch が英大文字であれば小文字に(例えば 'A' を 'a' に)、英小文字はそのまま小文字に変換します。つまり 'A' も 'a' も同じ文字とみなすことになります。
|
18
21
|
|
19
|
-
int c[INDEX('z'+1)]={0};
|
22
|
+
int c[INDEX('z' + 1)] = {0};
|
20
23
|
|
21
24
|
ここは、要素数26の配列を定義して(メモリを割り当てて)、その全ての要素を0で初期化しています。
|
22
|
-
- INDEX('z'+1) => 'z' + 1 - 'a' => 112 + 1 - 97 => 26
|
25
|
+
- INDEX('z'+1) => 'z' + 1 - 'a' => 112 + 1 - 97 => 26 であるから、
|
26
|
+
int c[INDEX('z' + 1)] は int c[26] と展開される。めでたしめでたし(アルファベットが26文字であることは常識の範疇だから最初から int c[26] = {0}; としても構わないと思う)。
|
23
|
-
- int c[INDEX('z'+1)]; だけだと、メモリ
|
27
|
+
- int c[INDEX('z'+1)]; としただけだと、メモリは割当られるが、値は不定になってしまう。各文字の出現回数を数えるには、最初の値をすべてを0にしておく(0に初期化する)必要がある。
|
24
|
-
- 「= {0}」 の部分で配列の全ての値を0で初期化する。ここに「
|
28
|
+
- 「= {0}」 の部分で配列の全ての値を0で初期化する。ここに「0」は一個しか書かれていないので c[0] = 0 だけが初期化されるかと思うと、さにあらず。初期値の指定がある場合、初期値が省略された c[1] ~ c[25] も初期値を0にするという約束なので。
|
25
29
|
|
26
30
|
P.S.
|
27
31
|
for(;(ch=getchar())!=EOF;){ でも良いけど
|