teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

'z' の値がタイポ

2021/06/25 08:31

投稿

rubato6809
rubato6809

スコア1382

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 == 112 です。
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' => 112 + 1 - 97 => 26 であるから、
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

説明を補足修正

2021/06/25 08:31

投稿

rubato6809
rubato6809

スコア1382

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']; とでもしたいところですが、それだと c[97] となってしまってダメ。そこで
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
- と変換できればよい。そこで INDEX(x) マクロを作れば
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で初期化する。ここに「」は一個しか書かれていないので c[0] = 0 だけかと思うとさにあらず初期値の指定がある場合、初期値省略された c[1] ~ c[25] も初期値を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;){ でも良いけど