基本情報技術者試験の過去問と解説
[TOP] [午前分野別] [午後分野別] [キーワード索引] [令和元年秋午前] [令和元年秋午後]

平成16年 春期 基本情報技術者 午後 問10
問10   C言語

〔プログラム1の説明〕

C 言語の仕様で記述された空でないソースプログラムを標準入力から読み込んで, 注釈を除去して標準出力へ出力するプログラムである。

(1) ソースプログラムの表記に関する説明

 @ このプログラムで扱う注釈は,文字定数,文字列リテラル又は注釈の中を除いて, “/*”で始まり“*/”で終わる文字の列である。

 A 使用可能文字の種類は,JIS X 0201(7 ビット及び 8 ビットの情報交換用符号化文字集合)である。 ただし,“ \ ”は“ \ ”と表記する。

 B 次のような記述はない。

 (i)  注釈の入れ子記述

 例 /* aaaaa /* bbbbbb */ ccccc */

 (ii) 図形文字の3文字表記

 ??= ??( ??/ ??' ??< ??> ??) ??! ??-

 C 文法上の誤りはない。

(2) プログラム1では,次の手順で注釈除去を行っている。 ただし,文字定数,文字列リテラル及び注釈の解析を単純に処理しているので, ソースプログラムの記述によっては,これらを正しく認識できずに誤った動作を起こす場合がある。

 @ 一重引用符又は二重引用符を検出すると,文字定数又は 文字列リテラルの開始と解釈し,関数 quote を使用して, 対応する一重引用符又は二重引用符を検出するまで,文字の列を読み込んでそのまま出力する。

 A “/*”を検出すると,注釈の開始と解釈し, 最初に現れる“*/”までの文字の列を読み飛ばす。

(3) プログラム1による注釈除去の実行例を図に示す。

入力ソースプログラム

/* This program uses fgets to display
 * a line from a file on the screen. */
#include <stdio.h>
int main( void )
{
   FILE *stream;   /* file pointer */
   char line[100]; /* input stream */
   if( (stream = fopen( "crt_fgets.txt", "r" )) != NULL )
   {
      if( fgets( line, 100, stream ) == NULL)
         printf( "fgets error\n" ); /* error message */
      else
         printf( "%s", line);
      fclose( stream );
   }
}

注釈を除去した後の出力結果

#include <stdio.h>
int main( void )
{
   FILE *stream;   
   char line[100]; 
   if( (stream = fopen( "crt_fgets.txt", "r" )) != NULL )
   {
      if( fgets( line, 100, stream ) == NULL)
         printf( "fgets error\n" ); 
      else
         printf( "%s", line);
      fclose( stream );
   }
}

   図 注釈除去の実行例

〔プログラム 1〕

#include <stdio.h>
void quote( char );
main()
{
    int c1, c2;
    while ( (c1 = getchar()) != EOF ) {
        /* 一重引用符の検出   */
        if ( c1 == '\'' ) quote( '\'' );
        /* 二重引用符の検出   */
        else if ( c1 == '\"' ) quote( '\"' );
        /* 斜線の検出        */
        else if ( c1 == '/' ) {
            c2 = getchar();
            /* 次の文字がアステリスクのとき    */
            if ( c2 == '*' ) {
                /* 注釈文字列の除去          */
                while ( 1 ) {
                    while ( (c1 = getchar()) != '*' ); 
                    c2 = getchar();
                    if ( c2 == '/' ) break;
                }
            }
            /* その他の場合   */
            else {
                putchar(c1);
                putchar(c2);
            }
        }
        else putchar(c1); /* 読み込んだ1文字をそのまま出力*/
    }
}
void quote( char c ) 
{   /* 文字定数及び文字列リテラルの抽出  */
    char cc;
    putchar(c);
    while ( (cc = getchar()) != c ) putchar(cc);
    putchar(cc);
}

基本情報技術者試験


設問1 プログラム1に入力すると誤った動作を起こす記述を,解答群の中から選べ。

解答群

ア /* "aaaaaaa" */

イ /* aaa 'a' */

ウ if ( c == '\'' ) {

エ printf( " \' " );

オ printf( "aaa /* comment */ \n" );

解答 ←クリックすると正解が表示されます

〔プログラム2の説明〕

プログラム2は,プログラム1の説明 (2) で指摘した問題点を解決するために, 次のように書き換えたものである。

(1) 文字定数,文字列リテラル,注釈の三つのモードに分けて処理する。

(2) “文字定数モード”は,一重引用符の出現によって, モードのオンとオフが切り替わる。 ただし,“ \ ”による拡張表記として記述されたもの,文字列リテラル内及び 注釈内に記述されたものは該当しない。

(3) “文字列リテラルモード”は,二重引用符の出現によって, モードのオンとオフが切り替わる。 ただし,“ \ ”による拡張表記として記述されたもの,文字定数内及び 注釈内に記述されたものは該当しない。

(4) “注釈モード”は,“/*”及び“*/”の出現によって, モードのオンとオフが切り替わる。 ただし,文字定数内及び文字列リテラル内に記述されたものは該当しない。

〔プログラム 2〕

#include <stdio.h>
main()
{
    int c1, c2;
    int c_mode = 0;          /* 注釈モードをオフに初期化           */
    int quote1 = 0;          /* 文字定数モードをオフに初期化       */
    int quote2 = 0;          /* 文字列リテラルモードをオフに初期化 */
    for ( c1 = getchar(); ( c2 = getchar()) != EOF; c1 = c2 ) {
        if ( !c_mode ) { /* 注釈モードがオフのとき                 */
            /* 文字定数又は文字列リテラルの中で文字 \ を検出           */
            if (  && c1 == '\\' ) {
                putchar(c1);
                putchar(c2);
                c2 = getchar();
                continue;
            }
            /* 文字列リテラル以外のところで一重引用符を検出         */
            else if ( !quote2 && c1 == '\'' )
                ;
            /* 文字定数以外のところで二重引用符を検出              */
            else if ( !quote1 && c1 == '\'' )
                ;
            /* 文字定数及び文字列リテラル以外で / と * を検出         */
            else if (  && c1 == '/' && c2 == '*' ) {
                ;
                c2 = getchar();
                continue;
            }
            putchar(c1);
        }
        else {
            if ( c1 == '*' && c2 == '/' ) {  /* 注釈の終端か? */
                ;
                c2 = getchar();
            }
        }
    }
    putchar(c1);
}

基本情報技術者試験


設問2 プログラム2中の に入れる正しい答えを,解答群の中から選べ。

a,d に関する解答群

ア !quote1    イ !quote2

ウ (!quote1 || !quote2)    エ (!quote1 && !quote2)

オ (quote1 || quote2)    カ (quote1 && quote2)

b,c,e に関する解答群

ア c_mode = !c_mode    イ c_mode = quote1 && quote2

ウ quote1 = !quote1    エ quote1 = !quote2

オ quote1 = quote2    カ quote2 = !quote1

キ quote2 = !quote2    ク quote2 = quote1

解答 a ←クリックすると正解が表示されます

解答 b ←クリックすると正解が表示されます

解答 c ←クリックすると正解が表示されます

解答 d ←クリックすると正解が表示されます

解答 e ←クリックすると正解が表示されます


[←前の問題] [次の問題→] [問題一覧表] [分野別] [基本情報技術者試験TOP ]