【問題17】字句解析プログラムを作ろう完全マスター! 組み込みC言語プログラミング(19)(1/3 ページ)

コンピュータは人間と違って自然に「文字(字句)」を認識することはできません。字句を識別させるには事前に何が字句かを定めて、その規則に沿ったプログラムを作る必要があります。

» 2015年03月13日 11時00分 公開
[横田一弘 埼玉県立新座総合技術高等学校 教諭,MONOist]

 本連載では、これから組み込みシステムのプログラミングを学びたい人向けに、C言語を使ったマイコン制御プログラムの“イロハ”を解説していきます。

 毎回少しずつステップアップしていけるよう、本文の最後で問題を出し、次回その解答と解説を紹介していきます。

プログラムの単語のカウント

問題17:

C言語のソースプログラムを読み取り、その中に単語がいくつあるか表示します。ただし単語とは、先頭の文字がアルファベットまたはアンダースコア(_)で、2文字目以降の文字がアルファベットまたはアンダースコアまたは数字とします。ダブルコーテーション(”)で囲まれた文字列リテラルやコメントは単語に含みません。

 人間は自然と単語(プログラム言語の予約語や識別子)を認識してプログラムを読むことができますが、コンピュータにとってプログラムは文字の並びにすぎません。ですからコンピュータに単語を識別させるには、「先頭の文字がアルファベットまたはアンダースコアで、2文字目以降の文字がアルファベットまたはアンダースコアまたは数字」のように単語がどんな文字の並びなのか定めて、その規則に従ってプログラムを作る必要があります。

 今回の課題ではファイルを扱いますが、fgetcを用いて、ファイルの先頭から1文字ずつ文字を読み取りながら単語を探していきます。しかしそれだけでは、文字列やコメントの中身も単語と認識してしまうので、それらを単語と区別する機能も備えています。

 それでは解答を発表します。

  1. /* wowd counter */
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. void skip_word(void);
  5. void skip_string(void);
  6. void skip_const_char(void);
  7. void skip_comment(void);
  8. FILE *fp;
  9. int ch;
  10. int main(void)
  11. {
  12. int count;
  13. fp = fopen("words.c", "r");
  14. if (fp == NULL) {
  15. printf("Can¥'t open file.¥n");
  16. return 1;
  17. }
  18. count = 0;
  19. ch = fgetc(fp);
  20. while (ch != EOF) {
  21. if (isalpha(ch) || (ch == '_')) {
  22. count++;
  23. skip_word();
  24. }
  25. else if (ch == '¥"') skip_string();
  26. else if (ch == '¥'') skip_const_char();
  27. else if (ch == '/') {
  28. ch =fgetc(fp);
  29. if (ch == '*') skip_comment();
  30. }
  31. else ch = fgetc(fp);
  32. }
  33. fclose(fp);
  34. printf("%d words¥n", count);
  35. return 0;
  36. }
  37. void skip_word(void)
  38. {
  39. ch = fgetc(fp);
  40. while (isalnum(ch) || (ch == '_')) ch = fgetc(fp);
  41. }
  42. void skip_string(void)
  43. {
  44. ch = fgetc(fp);
  45. while (ch != '¥"') {
  46. if (ch == '¥¥') ch = fgetc(fp);
  47. ch = fgetc(fp);
  48. }
  49. ch = fgetc(fp);
  50. }
  51. void skip_const_char(void)
  52. {
  53. ch = fgetc(fp);
  54. while (ch != '¥'') {
  55. if (ch == '¥¥') ch = fgetc(fp);
  56. ch = fgetc(fp);
  57. }
  58. ch = fgetc(fp);
  59. }
  60. void skip_comment(void)
  61. {
  62. ch = fgetc(fp);
  63. for (;;) {
  64. if (ch == '*') {
  65. ch = fgetc(fp);
  66. if (ch == '/') break;
  67. }
  68. ch = fgetc(fp);
  69. }
  70. ch = fgetc(fp);
  71. }
words.c

 words.cはいくつかの関数で構成されます。words.cの関数の一覧を以下に示します。

関数名 概要
main mainから実行が開始されます。
skip_word 単語が見つかったら呼ばれる関数です。単語が終わるまで戻りません。
skip_string 文字列が見つかったら呼ばれる関数です。文字列が終わるまで戻りません。
skip_const_char 文字定数が見つかったら呼ばれる関数です。文字定数が終わるまで戻りません。
skip_comment コメントが見つかったら呼ばれる関数です。コメントが終わるまで戻りません。

 month.cを実行すると、次のような結果になります。

photo
       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.