連載
» 2018年06月18日 10時00分 公開

山浦恒央の“くみこみ”な話(107):バグ検出ドリル(7)やっぱり、いろんなところにバグがいる! (2/3)

[山浦恒央 東海大学 大学院 組込み技術研究科 非常勤講師(工学博士),MONOist]

2.今回の問題

 同級生のA君とB君は、それぞれ自分で環境構築したPCを使って、授業の宿題で出たプログラム(仕様はリスト1を参照)を作ることになった。A君は、仕様に従ってリスト2のソースコードを作成した。リスト3に示す外部入力ファイル(data.txt)のデータを入力すると、リスト4の左の結果となった。

 B君は、最初に外部入力ファイルのデータを作成したが、作ったプログラムがうまく動かず、A君のプログラム(リスト2)をそのままコピーした。しかし、実行結果はリスト4の右となり、行番号、列番号が正しくない。なぜ、B君はA君と同じプログラムを実行しているのに、結果が異なったか推察せよ。

(1)概要

 外部入力ファイルから文字を1文字ずつ読み出し、コンソールから入力した文字と一致するまでの行数と列番号を表示せよ。

(2)仕様の詳細

(2-1)入力するファイル

 外部入力ファイルの名称は、「data.txt」とし、実行ファイルと同階層のフォルダに格納しておくこと。使用する文字コードは、「Shift-Jis」とし、下記に示す文字だけとする。

(2-1-1)半角大文字アルファベット(A〜Z)
(2-1-2)半角小文字アルファベット(a〜z)

(2-2)入力する文字

 コンソールから入力する文字は(2-1)に示した1文字を入力する。

(2-3)文字検索

 下記の処理を、ファイルの最終行まで繰り返す。

(2-3-1)data.txtから1文字入力する
(2-3-2)列数+1する
(2-3-3)コンソールから入力した値と一致する場合は、行数と列数を表示する
(2-3-4)data.txtから入力した文字が、改行を表すLF(ラインフィード)、その1つ前の入力がCR(キャリッジリターン)の場合は、文字数+1、列数=0とし(2-3-1)を実行する

(3)制限事項

 外部入力ファイルの名前は、「data.txt」とする。

 使用する外部入力ファイルは、自身の環境であらかじめ作成しておくこと。

 コンソール入力する文字は、異常な入力を考慮しない。

リスト1 行番号と列番号を表示するプログラムの仕様
#include <stdio.h>
#include <stdlib.h>
main(void) {
	FILE *fp;				//ファイルポインタ
	char in;					//コンソールからの入力用
	char ch;					//ファイルからの入力用
	int cr_flg = 0;				//CRを表すフラグ
	int linenum = 1;				//行数
	int row = 0;				//列数
	printf("1文字入力: ");
	scanf("%c",&in);				//1文字入力する
	//外部入力ファイル「data.txt」を呼び出す
	if ((fp = fopen("data.txt", "rb")) == NULL) {
		exit(1);
	}
	//ファイルから1文字ずつchに入力し、ファイルの最後まで繰り返す
	while( (ch = fgetc(fp)) != EOF) {
		row++;				//列数+1にする
		if (ch == in) {			//入力した文字が一致した場合
			printf("行数 : %d, 列番号 : %d\n",linenum, row);
		}
		if (ch == 0x0D) {			//ファイルにCRがある
			cr_flg = 1;			//CRフラグ=1にする
		} else if (ch == 0x0A && cr_flg == 1) {	//LFかつCRフラグ=1の場合
			linenum++;		//行数+1にする
			row = 0;			//列数=0にする
			cr_flg = 0;		//CRフラグを0にする
		}
	}
	fclose(fp);
リスト2 行番号と列番号を表示するプログラム
Apple
Orange
Grape
Carrot
Strawberry
Blueberry
リスト3 外部入力ファイル(data.txt)
リスト4 リスト4 A君(左)とB君(右)の実行結果

Copyright © ITmedia, Inc. All Rights Reserved.