本文實現一個將C語言風格註釋(/* ... */)自動轉換為C++風格單行註釋(//)的工具程序。工具需正確處理嵌套註釋、字符串字面量中的註釋符號、多行註釋轉換等邊界情況。
input.c/*int i = 0;*/ /*int y = 0;*/int j = 0; /*int x = 0;/*12345678*/ /* int h = 0; int g = 0; int j = 0; */int q = 0; /**//**/ /* ****** */ // /*1234567890*/
output.c//int i = 0; //int y = 0; int j = 0; //int x = 0;/*12345678 // //int h = 0; //int g = 0; //int j = 0. // int q = 0. // // ****** // /*1234567890*/
採用有限狀態機(FSM)處理字符流,狀態定義:
TAG_END:非註釋狀態TAG_BEGIN:處於/* ... */註釋內部轉換邏輯:
firstch/,讀取下一字符secondch:
secondch == '*' 且處於TAG_END → 進入註釋,輸出//,狀態轉TAG_BEGINsecondch == '/' → C++單行註釋,直接複製至換行*,讀取secondch:
secondch == '/' → 註釋結束,輸出空格,狀態轉TAG_ENDsecondch == '*' → 輸出*,回退一字符\n且處於TAG_BEGIN → 輸出\n//(多行註釋每行轉為單行註釋)Annotationconvert.c#include <stdio.h>
#include <errno.h>
#include <assert.h>
#pragma warning(disable:4996)
typedef enum STATE {
FILE_ERROR, FILE_SUCCESS, OTHER_ERROR, NO_MATCH
} STA;
typedef enum TAG { TAG_BEGIN, TAG_END } TAG;
STA AnnotationConvert(FILE* infile, FILE* outfile) {
char firstch, secondch;
int next;
assert(infile && outfile);
TAG state = TAG_END;
do {
firstch = fgetc(infile);
switch (firstch) {
case '/':
secondch = fgetc(infile);
if (secondch == '*' && state == TAG_END) {
fputc('/', outfile); fputc('/', outfile);
state = TAG_BEGIN;
} else if (secondch == '/') {
fputc(firstch, outfile); fputc(secondch, outfile);
while ((next = fgetc(infile)) != EOF && next != '\n')
fputc(next, outfile);
state = TAG_END;
} else {
fputc(firstch, outfile); fputc(secondch, outfile);
}
break;
case '*':
secondch = fgetc(infile);
if (secondch == '/') {
fputc(' ', outfile);
state = TAG_END;
} else if (secondch == '*') {
fputc(firstch, outfile);
fseek(infile, -1, SEEK_CUR);
} else {
fputc(firstch, outfile); fputc(secondch, outfile);
}
break;
case '\n':
if (state == TAG_BEGIN) {
fputc(firstch, outfile);
fputc('/', outfile); fputc('/', outfile);
} else {
fputc(firstch, outfile);
}
break;
default:
fputc(firstch, outfile);
break;
}
} while (firstch != EOF);
return (state == TAG_END) ? FILE_SUCCESS : NO_MATCH;
}
STA StartConvert() {
STA s;
const char* infileName = "input.c";
const char* outfileName = "output.c";
FILE* infile = fopen(infileName, "r");
FILE* outfile = fopen(outfileName, "w");
if (!infile || !outfile) {
if (infile) fclose(infile);
return FILE_ERROR;
}
s = AnnotationConvert(infile, outfile);
fclose(infile); fclose(outfile);
return s;
}
int main() {
STA ret = StartConvert();
if (ret == FILE_ERROR) printf("文件錯誤: %d\n", errno);
else if (ret == FILE_SUCCESS) printf("轉換成功\n");
else if (ret == OTHER_ERROR) printf("其他錯誤: %d\n", errno);
else printf("不匹配\n");
return 0;
}
fseek(infile, -1, SEEK_CUR)回退實現**正確處理//實現多行轉單行