回答編集履歴

2

'z' の値がタイポ

2021/06/25 08:31

投稿

rubato6809
rubato6809

スコア1380

test CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  'a' == 0x61 == 97
14
14
 
15
- 'z' == 0x7a == 112 です。
15
+ 'z' == 0x7a == 122 です。
16
16
 
17
17
  アルファベットは 'a' ~ 'z' の26文字あるので、出現回数を保持する配列の要素数は26必要です。したがって int c[26]; としたい。
18
18
 
@@ -46,7 +46,7 @@
46
46
 
47
47
  ここは、要素数26の配列を定義して(メモリを割り当てて)、その全ての要素を0で初期化しています。
48
48
 
49
- - INDEX('z'+1) => 'z' + 1 - 'a' => 112 + 1 - 97 => 26 であるから、
49
+ - INDEX('z'+1) => 'z' + 1 - 'a' => 122 + 1 - 97 => 26 であるから、
50
50
 
51
51
  int c[INDEX('z' + 1)] は int c[26] と展開される。めでたしめでたし(アルファベットが26文字であることは常識の範疇だから最初から int c[26] = {0}; としても構わないと思う)。
52
52
 

1

説明を補足修正

2021/06/25 08:31

投稿

rubato6809
rubato6809

スコア1380

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