工作目的:学习如何使用标准C库的函数来处理文件
任务: 有一个包含 C 程序的文件。有必要删除其中的所有注释并将没有注释的代码写入新文件。
解释和实施特点:
输入输出数据: 源文件始终命名为 test.c 输出文件必须命名为 test.wc
我的代码:
#include <stdio.h>
#define TRUE 1
#define FALSE 0
typedef int BOOL;
int mygetc (FILE *in) {
for (;;) {
int c = getc(in);
if (c == '\\') {
c = getc(in);
if (c == '\n')
continue;
if (c != EOF)
ungetc(c, in);
c = '\\';
}
return c;
}
}
int skip_line_comment (FILE *in) {
int c;
while ((c = mygetc(in)) != '\n' && c != EOF)
continue;
return c;
}
int skip_block_comment (FILE *in) {
int c;
for (;;) {
while ((c = mygetc(in)) != '*') {
if (c == EOF)
return c;
}
while ((c = mygetc(in)) == '*')
continue;
if (c == EOF)
return c;
if (c == '/')
return ' ';
}
}
void removeComments (FILE *in, FILE *out) {
int c;
while ((c = mygetc(in)) != EOF) {
if (c == '"' || c == '\'') {
int separator = c;
fputc(c, out);
while ((c = mygetc(in)) != separator && c != EOF) {
fputc(c, out);
if (c == '\\') {
c = mygetc(in);
if (c == EOF) break;
fputc(c, out);
}
}
} else if (c == '/') {
c = mygetc(in);
if (c == '/') c = skip_line_comment(in);
else if (c == '*') c = skip_block_comment(in);
else fputc('/', out);
}
if (c == EOF) break;
fputc(c, out);
}
}
int main () {
const char inName[20] = "test.c";
const char outName[20] = "test.wc";
FILE *in;
FILE *out;
in = fopen(inName, "r");
out = fopen(outName, "w");
removeComments(in, out);
fclose(in);
fclose(out);
return 0;
}
.zip 包含测试: Google Disk
这个问题有多个问题:
尚不清楚输出程序是否与源程序有细微的差别,例如
\
后跟行尾序列)测试文件使用 DOS 行结束序列 (CR/LF) 进行编码,预期输出文件使用 unix 行结束 (LF) 和 DOS 行结束序列的不一致组合。该zip文件还包含macOS属性文件(在__MACOSX/目录中),表明它是在Mac上生成的,Mac使用unix行结尾,并且不会翻译以文本模式打开的文件的行结尾(
"r"
和) "w"
)。预期的输出文件很可能是在 mac 或 unix 系统上从 DOS 源文件生成的,其中 DOS 行尾序列是从源文件中原样复制的,将 '\n'
输出替换为多行注释未翻译通过标准库将 CR/LF 序列转换为 CR/LF 序列,就像它们在遗留系统上一样。
测试文件包含许多不一致之处,例如缺少空格和换行符。问题陈述应该更精确,指定单行注释应替换为单个换行符,多行注释应替换为单个空格。
这使得编写能够精确产生预期输出的程序变得困难。
您的程序非常简单并且看起来正确,但会有一些限制和错误:
如果在unix系统上编译,它无法识别CR/LF序列,因此它不会将CR/LF后面的
\
处理为转义换行符。这会阻止正确处理注释,其中 //
、/*
或 */
序列被分成两行并带有转义换行符。
程序不会将序列
/"
处理为 /
后跟字符串开头,因为 "
是由正文末尾的 fputc(c, out)
输出的,并且仅测试下一个字符的 '
或 "
。同样的问题/'
。
程序会抑制所有转义换行符,包括那些外部注释,这不是测试文件所期望的。