从文件中删除c条评论

时间:2016-07-18 03:07:08

标签: c file-io comments

我知道此类问题之前已得到解答,但我有自己的解决方案,我想解决其中的错误。我并不担心引用评论,我知道这段代码不会处理它们。问题是从/注释开始的初始/* … */会在不应该的时候打印到文件中。

int cleanFile( char *fileName ){

FILE *fp;
fp = fopen(fileName, "r");
int inComment = 0;
char current, next;

//will return exit exicution if the file does not exist
if(fp == NULL){
    printf("%s", "File was not found.\nFile is expected to be in src directory.");
    return 0;
}
//creat a new file for the clean input
FILE *cf;
cf = fopen( "cleaninput.txt", "w" );

current = fgetc(fp);

while(current != EOF){

    if( inComment == 0 ){

        if(current == '/')
        {
            next = fgetc(fp);

                //look ahead and see if this is the start of a comment
                if(next == '*')
                {

                    inComment = 1;
                    current = next;   //CODE JUMPS FROM HERE 

                }else{

                    fputc(current, cf);
                    current = next;

                }
        }else{
            fputc(current, cf);
            current = fgetc(fp); // AND LANDS HERE
        }

    //if an exit sequence is found set in comment to false
    }else{
        if(current == '*')
        {
            next = fgetc(fp);
            if(next == '/')
            {
                inComment = 0;
                current = next;
            }
        }else{
            current = fgetc(fp);
        }
    }
}//end while

fclose(fp);
fclose(cf);

return 1;
}

2 个答案:

答案 0 :(得分:1)

问题不在于打印了前导/,而是打印了尾随/。您可以通过将current设置为下一个输入字符而不是nextnext /时的#include <stdio.h> static int cleanFile(char *fileName) { FILE *fp; fp = fopen(fileName, "r"); int inComment = 0; int current, next; /* will return exit execution if the file does not exist */ if (fp == NULL) { printf("%s", "File was not found.\nFile is expected to be in src directory."); return 0; } /* create a new file for the clean input */ FILE *cf = fopen("cleaninput.txt", "w"); current = fgetc(fp); while (current != EOF) { if (inComment == 0) { if (current == '/') { next = fgetc(fp); if (next == EOF) { fputc(current, cf); break; } /* look ahead and see if this is the start of a comment */ if (next == '*') { inComment = 1; current = fgetc(fp); } else { fputc(current, cf); current = next; } } else { fputc(current, cf); current = fgetc(fp); } } else if (current == '*') { next = fgetc(fp); if (next == '/') { inComment = 0; current = fgetc(fp); } else { current = next; } } else { current = fgetc(fp); } }/* end while */ fclose(fp); fclose(cf); return 1; } int main(int argc, char **argv) { char *filename = "cc23.c"; if (argc == 2) filename = argv[1]; if (cleanFile(filename)) printf("OK\n"); else printf("Oops!\n"); return 0; } 来解决此问题。

使用其他一些(最小)修复:

int fpeekc(FILE *fp)
{
    int c = getc(fp);
    if (c != EOF)
        ungetc(c, fp);
    return c;
}

一个小问题是,这并不能用空白替换注释,这可能会改变程序的含义(或有效性)。

如果是我自己的代码,我会使用一个函数来查看下一个字符:

#include <assert.h>
#include <stdio.h>

/*
 * This is adequate for routine comments.
 * It wouldn't spot /\
 * * as the start of a comment, or *\
 * / as the end of a comment (where the " * " line prefix should be ignored).
 */

static int fpeekc(FILE *fp)
{
    int c = getc(fp);
    if (c != EOF)
        ungetc(c, fp);
    return c;
}

static void cleanFile(FILE *fin, FILE *fout)
{
    int inComment = 0;
    int current, next;

    while ((current = getc(fin)) != EOF)
    {
        if (inComment == 0)
        {
            if (current == '/' && fpeekc(fin) == '*')
            {
                next = getc(fin);
                assert(next == '*');
                inComment = 1;
            }
            else
                putc(current, fout);
        }
        else if (current == '*' && fpeekc(fin) == '/')
        {
            inComment = 0;
            next = fgetc(fin);
            assert(next == '/');
        }
        /* else do not echo comment characters */
    }
}

int main(int argc, char **argv)
{
    char *filename = "cc29.c";
    if (argc == 2)
        filename = argv[1];
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        return 1;
    }
    cleanFile(fp, stdout);
    return 0;
}

它将简化先行逻辑。我还重新设计了一个函数来处理已打开的文件流并写入指定的文件流 - 它使代码更加通用。

'/*'

反斜杠 - 换行组合使注释处理变得复杂 - 幸运的是,除非您正在编写C预处理器,否则您可能不需要担心它们。您必须担心字符串和多字符文字,例如TEXT - 后者不可移植,但仍然有效且不会发表评论。而C ++原始字符串又是另一个复杂程度。

答案 1 :(得分:0)

假设评论不跨越多行,如果在第一个字符以正斜杠开头时忽略整行,则不会更容易吗?

我认为问题可能在你的第二个IF声明中,检查你的条件表达式。如果读取的字符不是星号,则程序会立即写入文件。

如果您的源代码中包含以下行。

// Something here

你的程序读取第一个字符,在这种情况下是正斜杠,然后它读取第二个字符,它也是正斜杠,而不是星号。因此,执行ELSE语句会导致程序写入输出文件而不是忽略整行。