**工作目的:**学习如何使用标准C库的函数处理文件
**任务:**有一个C程序的文件,需要删除其中的所有注解,将没有注解的代码写到一个新文件中。
解释和实现特性:
1.程序文件可能非常大,因此,不能事先将整个文件读入数组。
1.注解可以是单行或多行。如果使用“反斜杠”字符-“"将单行注解移到下一行,则单行注解也可以由多行组成。
1.在C语言中没有嵌套注解
1.不考虑字符串常量内的注解
1.一个文件不一定代表一个正确的C程序。例如,一个注解可能会在没有关闭的情况下断开
1.允许出现一些新的空格和/或换行符来代替已删除的注解,也允许缺少一些现有的非重要分隔符字符。
1.不允许从用引号(双引号和单引号)标记的常量字符串中删除数据。
**输入和输出数据:**源文件始终命名为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
1.测试1 -正确
1.测试2 -正确
1.测试3 -第一行中缺少“/”
1.测试4 -在一行中预期“*”,但在不同的行中得到 *
1.测试5 -正确
1.测试6 -““出现问题,得到一些必须删除的额外行,如“"\”
1.测试7 -正确
1.测试8 -剥离多余的管路
1.测试9、10 -组合/和\的问题
1.测试11 -正确
1.测试12 -正确
1.测试13 -正确
2条答案
按热度按时间dxpyg8gm1#
这个问题涉及多个问题:
\
后跟和行尾序列)"r"
和"w"
)。很可能预期的输出文件是在Mac或Unix系统上从DOS源文件生成的,其中DOS行尾序列是源文件中未更改的副本,但替换多行注解的'\n'
输出没有被标准库转换为CR/LF序列,因为它们在遗留系统上会被转换。#define a/**/(b)
中,这将导致a(1)
被定义为扩展到(b)(1)
而不是什么都没有。如果多行注解的缺失会导致下一个字符成为前一个标记的一部分,则多行注解仅应扩展为空格,这对于实现来说并不简单。似乎很难编写一个程序来精确地产生预期的输出。
您的程序非常简单,似乎是正确的,除了一些限制和错误:
\
后跟CR/LF作为转义换行符处理。这会阻止正确处理//
,/*
或*/
序列被分成两行并带有一个或多个转义换行符的注解。/"
作为一个/
后跟一个字符串的开始,因为"
是由fputc(c, out)
在主体的末尾输出的,只有下一个字符与'
和"
进行比较。/'
也有同样的问题。??/
这样的三重字符,在删除转义换行符 * 之前 * 转换为\
(对三重字符的支持将是迂腐的,因为这个功能已经从最新的C标准中删除了,除了在测试套件中,从来没有使用过)。int x = 1'000;
)。这种丑陋的约定使得正确解析C标记更加困难。非常不幸的是,C23没有像几乎所有其他现代语言那样将_
标准化为数字分隔符,与现有的预处理器和解析器兼容的约定X1 m22n1x已经在pp-numbers中被接受。X1 m23n1x将被解释为开始字符常量,导致程序的其余部分被错误解释,并导致注解剥离失败。这是你的程序的修改版本,修正了行尾问题和
/"
和/'
解析错误。它仍然抑制转义的换行符,忽略三字母组,并将'
误解为数字分隔符。字符串
tmb3ates2#
决定完全重写程序。现在每种情况都有一个单独的算法。它通过了所有13个测试。
字符串