在 C 中删除内联注释时的意外行为
Unexpected behaviour when removing inline comments in C
堆栈溢出!我正在学习C技术。我有一个获取输入文件、查找文件并将内容写入输出文件而不带注释的函数。
该功能有效,但在某些情况下也会刹车。
我的函数:
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(ouput,"w");
char c;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n');
}
else
{
fputc('/', out);
}
}
else
{
fputc(c,out);
}
}
fclose(in);
fclose(out);
}
但是当我将这样的文件作为输入时:
// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b)
{
return a + b; // An inline comment.
}
int sample = sample;
删除内联注释时,由于某种原因它无法到达 '\n' 并给出输出:
int add(int a, int b)
{
return a + b; }
int sample = sample;
[编辑]
谢谢你帮助我!它适用于我发布的案例,但它在另一个案例中刹车。
当前代码:
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
int startline = 1;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
if (! startline)
fputc('\n', out);
startline = 1;
}
else if (c == EOF)
break;
else {
fputc('/', out);
startline = 0;
}
}
else
{
fputc(c,out);
startline = (c == '\n');
}
}
fclose(in);
fclose(out);
当文件包含除法时,第二个变量消失。
示例:
int divide(int a, int b)
{
return a/b;
}
它回馈:
int divide(int a, int b)
{
return a/;
}
之后
while((c = fgetc(in)) != '\n');
你需要一个fputc('\n', out);
补充说明:
在
char c;
while((c = fgetc(in)) != EOF)
c 必须是 int 才能管理 EOF
只是一个打字错误:ouput 必须是 output 才能编译
你读了一个'/'后没有很好地管理EOF
您错过了检查 fopen
的结果
提议:
#include <stdio.h>
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
fputc('\n', out);
}
else if (c == EOF) {
fputc('/', out);
break;
}
else
fputc('/', out);
fputc(c, out);
}
else
{
fputc(c,out);
}
}
fclose(in);
fclose(out);
/* change signature to return 1 ? */
}
int main(int argc, char ** argv)
{
removeComments(argv[1], argv[2]);
}
正如 Tormund Giantsbane 在评论中所说,最好完全删除仅包含评论的行(评论从第一列开始),新提案就是这样做的:
#include <stdio.h>
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
int startline = 1;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
if (! startline)
fputc('\n', out);
startline = 1;
}
else if (c == EOF) {
fputc('/', out);
break;
}
else {
fputc('/', out);
fputc(c, out);
startline = 0;
}
}
else
{
fputc(c,out);
startline = (c == '\n');
}
}
fclose(in);
fclose(out);
/* change signature to return 1 ? */
}
int main(int argc, char ** argv)
{
removeComments(argv[1], argv[2]);
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -g r.c
pi@raspberrypi:/tmp $ cat i
// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b)
{
return a + b/c; // An inline comment.
}
int sample = sample;
pi@raspberrypi:/tmp $ ./a.out i o
pi@raspberrypi:/tmp $ cat o
int add(int a, int b)
{
return a + b/c;
}
int sample = sample;
正如 DavidC 所说。在注释中,如果 // 放在字符串中,结果将不是预期的结果,字符甚至非法也是这种情况(我的意思是 '//' 不能更改),C 注释(/ * .. // ... */) 等
When removing the inline comment it fails to reach the '\n' for some reason
嗯,不,如果它未能到达或看到内联注释末尾的换行符,那么程序可能会消耗整个文件的其余部分。它实际上没有做的是 write 这样的换行符到输出。
考虑一下你的评论代码:
while((c = fgetc(in)) != '\n');
该循环在读取换行符时终止。此时,已经读取的换行符无法再次从输入中读取,因此您的一般读/写规定将不会处理它。如果你想保留这样的换行符,那么你需要在评论处理分支中打印它们。
补充说明:
fgetc
returns 一个 int
,而不是一个 char
,你需要这样处理它才能正确检测文件结尾。
如果输入以内联注释结束,而没有换行符终止,您的程序将进入无限循环。这样的来源在技术上是不合格的,但即便如此,你也应该处理它。
堆栈溢出!我正在学习C技术。我有一个获取输入文件、查找文件并将内容写入输出文件而不带注释的函数。 该功能有效,但在某些情况下也会刹车。 我的函数:
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(ouput,"w");
char c;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n');
}
else
{
fputc('/', out);
}
}
else
{
fputc(c,out);
}
}
fclose(in);
fclose(out);
}
但是当我将这样的文件作为输入时:
// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b)
{
return a + b; // An inline comment.
}
int sample = sample;
删除内联注释时,由于某种原因它无法到达 '\n' 并给出输出:
int add(int a, int b)
{
return a + b; }
int sample = sample;
[编辑] 谢谢你帮助我!它适用于我发布的案例,但它在另一个案例中刹车。 当前代码:
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
int startline = 1;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
if (! startline)
fputc('\n', out);
startline = 1;
}
else if (c == EOF)
break;
else {
fputc('/', out);
startline = 0;
}
}
else
{
fputc(c,out);
startline = (c == '\n');
}
}
fclose(in);
fclose(out);
当文件包含除法时,第二个变量消失。 示例:
int divide(int a, int b)
{
return a/b;
}
它回馈:
int divide(int a, int b)
{
return a/;
}
之后
while((c = fgetc(in)) != '\n');
你需要一个fputc('\n', out);
补充说明:
在
char c;
while((c = fgetc(in)) != EOF)
c 必须是 int 才能管理 EOF
只是一个打字错误:ouput 必须是 output 才能编译
你读了一个'/'后没有很好地管理EOF
您错过了检查 fopen
的结果提议:
#include <stdio.h>
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
fputc('\n', out);
}
else if (c == EOF) {
fputc('/', out);
break;
}
else
fputc('/', out);
fputc(c, out);
}
else
{
fputc(c,out);
}
}
fclose(in);
fclose(out);
/* change signature to return 1 ? */
}
int main(int argc, char ** argv)
{
removeComments(argv[1], argv[2]);
}
正如 Tormund Giantsbane 在评论中所说,最好完全删除仅包含评论的行(评论从第一列开始),新提案就是这样做的:
#include <stdio.h>
void removeComments(char* input, char* output)
{
FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");
if (in == NULL) {
printf("cannot read %s\n", input);
return; /* change signature to return 0 ? */
}
if (out == NULL) {
printf("cannot write in %s\n", output);
return; /* change signature to return 0 ? */
}
int c;
int startline = 1;
while((c = fgetc(in)) != EOF)
{
if(c == '/')
{
c = fgetc(in);
if(c == '/')
{
while((c = fgetc(in)) != '\n')
{
if (c == EOF) {
fclose(in);
fclose(out);
return; /* change signature to return 1 ? */
}
}
if (! startline)
fputc('\n', out);
startline = 1;
}
else if (c == EOF) {
fputc('/', out);
break;
}
else {
fputc('/', out);
fputc(c, out);
startline = 0;
}
}
else
{
fputc(c,out);
startline = (c == '\n');
}
}
fclose(in);
fclose(out);
/* change signature to return 1 ? */
}
int main(int argc, char ** argv)
{
removeComments(argv[1], argv[2]);
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -g r.c
pi@raspberrypi:/tmp $ cat i
// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b)
{
return a + b/c; // An inline comment.
}
int sample = sample;
pi@raspberrypi:/tmp $ ./a.out i o
pi@raspberrypi:/tmp $ cat o
int add(int a, int b)
{
return a + b/c;
}
int sample = sample;
正如 DavidC 所说。在注释中,如果 // 放在字符串中,结果将不是预期的结果,字符甚至非法也是这种情况(我的意思是 '//' 不能更改),C 注释(/ * .. // ... */) 等
When removing the inline comment it fails to reach the '\n' for some reason
嗯,不,如果它未能到达或看到内联注释末尾的换行符,那么程序可能会消耗整个文件的其余部分。它实际上没有做的是 write 这样的换行符到输出。
考虑一下你的评论代码:
while((c = fgetc(in)) != '\n');
该循环在读取换行符时终止。此时,已经读取的换行符无法再次从输入中读取,因此您的一般读/写规定将不会处理它。如果你想保留这样的换行符,那么你需要在评论处理分支中打印它们。
补充说明:
fgetc
returns 一个int
,而不是一个char
,你需要这样处理它才能正确检测文件结尾。如果输入以内联注释结束,而没有换行符终止,您的程序将进入无限循环。这样的来源在技术上是不合格的,但即便如此,你也应该处理它。