#include <stdio.h>
#include <stdbool.h>
void m_cmnt(FILE *fp) {
int prev;
int ch;
while ((ch = getc(fp)) != EOF) {
if (prev == '*' && ch == '/') {
return;
} else
prev = ch;
}
}
int main(int c, char **arr) {
FILE *fp, *np;
int ch, prev;
bool String = 0;
fp = fopen("test.txt", "r");
np = fopen("temp.txt", "w");
if (fp == NULL) {
printf("Invalid/No Filename given as Argument ! \n");
return 1;
}
while ((ch = getc(fp)) != EOF) {
if (!String) {
if (ch == '/') {
prev = ch;
ch = getc(fp);
switch (ch) {
case '*':
/* if(ch != 'a') putc('h', np); */
m_cmnt(fp);
putc(' ', np);
break;
default:
putc(prev, np);
putc(ch, np);
break;
}
} else
putc(ch, np);
} else
putc(ch, np);
if (ch == '\"' || ch == '\'')
String = !String;
prev = ch;
}
fclose(fp);
fclose(np);
remove(arr[1]);
//rename("temp.txt", arr[1]);
return 0;
}
这是一个简单的注释掉的C程序(它是C预处理程序的工作)。当检测到标准错误流中的未终止注释(/* example
)时,我在添加一项功能以编写一条错误消息时很费劲。错误应该说类似Error: line X: unterminated comment
,其中X是发生错误的行号。我已经尝试了好几天了,但是我没有任何进展,我感到非常沮丧。因此,请有人帮助我提供简单明了的答案。
test.txt
hello\nworld
Me/*some\ncomment*/again
程序运行后的test.txt结果应该是
hello
world
me
again
它们两个都位于单独的行中,因为在每种情况下都存在\ n。但是我现在得到的是
hello\nworld
Me again
答案 0 :(得分:0)
如果在扫描m_cmnt()
时遇到EOF
,您可以修改*/
函数以输出错误消息:
void m_cmnt(FILE *fp) {
int prev, ch;
for (prev = 0; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '*' && ch == '/')
return;
}
fprintf(stderr, "error: unterminated comment\n");
}
如果要输出行号,则必须随时随地跟踪行数。
请注意,您也应该处理//
条注释,并更准确地解析字符串,以处理转义序列。
以下是具有行号处理的版本:
#include <stdio.h>
#include <stdbool.h>
/* skip a C multi-line comment, return the last byte read or EOF */
int m_cmnt(FILE *fp, int *lineno_p) {
int prev, ch, replacement = ' ';
for (prev = 0; (ch = getc(fp)) != EOF; prev = ch) {
if (ch == '\n') {
replacement = '\n';
++*lineno_p;
}
if (prev == '*' && ch == '/')
return replacement;
}
return EOF;
}
int main(int c, char **arr) {
FILE *fp, *np;
int ch;
bool String = 0;
const char *filename = "test.txt";
int lineno = 1;
fp = fopen(filename, "r");
np = fopen("temp.txt", "w");
if (fp == NULL) {
printf("cannot open input file %s\n", filename);
return 1;
}
while ((ch = getc(fp)) != EOF) {
if (ch == '\n')
lineno++;
if (!String) {
if (ch == '/') {
ch = getc(fp);
if (ch == '\n')
lineno++;
if (ch == '*') {
int startline = lineno;
ch = m_cmnt(fp, &lineno);
if (ch == EOF) {
fprintf(stderr, "%s:%d: error: unterminated comment started on line %d\n",
filename, *lineno, startline);
break;
}
putc(ch, np);
} else {
putc('/', np);
putc(ch, np);
}
} else {
putc(ch, np);
}
} else {
putc(ch, np);
}
if (ch == '\"' || ch == '\'')
String = !String;
}
fclose(fp);
fclose(np);
remove(arr[1]);
//rename("temp.txt", arr[1]);
return 0;
}
为说明起见,这是一个更完整的程序,可以处理字符和字符串常量以及转义的换行符的所有特殊情况:
/* 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;
}
if (ch == '\n')
++*lineno_p;
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, replacement = ' ';
while ((ch = getcpp(fp, &lineno)) != EOF) {
if (ch == '/' && lastc == '*') {
break;
}
if (ch == '\n')
replacement = '\n';
lastc = ch;
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated comment\n",
filename, startline);
break;
}
putc(replacement, 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;
}