现在此代码不会删除内嵌注释,如何更改它以便也删除内嵌注释?
FILE *output;
output = fopen("preprocess_output.c", "w");
while (fgets(line, LINE_LENGTH, file) != NULL)
{
for (int i = 0; i < strlen(line); i++)
{
if (line[i] == '/' && line[i + 1] == '/')
{
comment_lines++;
}
else
{
fprintf(output, line);
}
if (line[i] != '\n' && line[i] != '\t')
{
non_blank++;
break;
}
}
}
答案 0 :(得分:0)
这是一个几乎可以在所有情况下去除C注释的小程序。
/* strip C comments by chqrlie */
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* read the next byte from the C source file, handing escaped newlines */
int getcpp(FILE *fp, int *lineno_p) {
int ch;
while ((ch = getc(fp)) == '\\') {
if ((ch = getc(fp)) != '\n') {
ungetc(ch, fp);
return '\\';
}
*lineno_p += 1;
}
if (ch == '\n')
*lineno_p += 1;
return ch;
}
int main(int argc, char *argv[]) {
FILE *fp = stdin, *ft = stdout;
const char *filename = "<stdin>";
int ch, lineno;
if (argc > 1) {
if ((fp = fopen(filename = argv[1], "r")) == NULL) {
fprintf(stderr, "Cannot open input file %s: %s\n",
filename, strerror(errno));
return 1;
}
}
if (argc > 2) {
if ((ft = fopen(argv[2], "w")) == NULL) {
fprintf(stderr, "Cannot open output file %s: %s\n",
argv[2], strerror(errno));
return 1;
}
}
lineno = 1;
while ((ch = getcpp(fp, &lineno)) != EOF) {
int startline = lineno;
if (ch == '/') {
if ((ch = getcpp(fp, &lineno)) == '/') {
/* single-line comment */
while ((ch = getcpp(fp, &lineno)) != EOF && ch != '\n')
continue;
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated single line comment\n",
filename, startline);
break;
}
putc('\n', ft); /* replace comment with newline */
continue;
}
if (ch == '*') {
/* multi-line comment */
int lastc = 0;
while ((ch = getcpp(fp, &lineno)) != EOF) {
if (ch == '/' && lastc == '*') {
break;
}
lastc = ch;
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated comment\n",
filename, startline);
break;
}
putc(' ', ft); /* replace comment with single space */
continue;
}
putc('/', ft);
/* keep parsing to handle n/"a//"[i] */
}
if (ch == '\'' || ch == '"') {
int sep = ch;
const char *const_type = (ch == '"') ? "string" : "character";
putc(sep, ft);
while ((ch = getcpp(fp, &lineno)) != EOF) {
putc(ch, ft);
if (ch == sep)
break;;
if (ch == '\\') {
if ((ch = getcpp(fp, &lineno)) == EOF)
break;
putc(ch, ft);
}
if (ch == '\n') {
fprintf(stderr, "%s:%d: unescaped newline in %s constant\n",
filename, lineno - 1, const_type);
/* This is a syntax error but keep going as if constant was terminated */
break;
}
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated %s constant\n",
filename, startline, const_type);
break;
}
continue;
}
putc(ch, ft);
}
if (fp != stdin)
fclose(fp);
if (ft != stdout)
fclose(ft);
return 0;
}
由于免费获得了完整答案,请尝试学习上述代码如何处理字符串和转义的换行符。仍然有一些不支持的极端情况,您能找到它们吗?
\
个字符。答案 1 :(得分:-1)
在以下解决方案中,该行只有一次通过。如果找到评论(//
),我们将终止并打印它。支持(/* */
)需要做更多的工作。
while (fgets(line, LINE_LENGTH, file) != NULL)
{
size_t len = strlen(line);
size_t i;
for (i=0; i<len; i++)
{
if (line[i]=='/' && line[i + 1]=='/')
{
line[i] = '\0';
break;
}
}
fprintf(output, "%s", line);
}
除了逻辑上要注意两点:
使用printf
打印时,请始终使用格式字符串。如果该行包含%,则可能会发生意外的情况。
请勿将strlen
置于循环状态。它会产生很多不必要的循环来计算长度。
答案 2 :(得分:-1)
您将需要在文件中的任何表示注释的代码中扫描任何 "\\"
或"\*"
(因此,您< / em>在您的代码中检测到注释),将其忽略,然后检查它们分别以'\n'
和"*/"
结尾的位置 ,然后从那里继续书写。 ..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE * file;
FILE * output;
if (fopen_s(&file, "some_src.c", "r") != 0) {
fprintf(stderr, "File reading failure!");
return 1;
}
if (fopen_s(&output, "preprocess_output.c", "w") != 0) {
fprintf(stderr, "File writing failure!");
return 1;
}
int comment = 0;
char prev_ch, ch;
for (prev_ch = fgetc(file), ch = fgetc(file); ch != EOF; prev_ch = ch, ch = fgetc(file)) {
if (comment == 0 && prev_ch == '/')
{
if (ch == '/')
comment = 1;
else if (ch == '*')
comment = 2;
}
if (comment == 0)
fprintf(output, "%c", prev_ch);
if (comment == 1 && prev_ch != '\\' && ch == '\n')
comment = 0;
if (comment == 2 && prev_ch == '*' && ch == '/')
{
ch = fgetc(file);
comment = 0;
}
}
if (comment == 0)
fprintf(output, "%c", prev_ch);
fclose(file);
fclose(output);
return 0;
}
注意:由于许多人都指出了为什么我在代码中使用
\
而不是/
斜杠,因此请尝试使用此Demo来找出原因?>