Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove comments from C program

Tags:

c

comments

Following is my code to remove comments from a C program. But the comment lines don't get removed. It removes /* and */, but doesn't remove the sentence between this delimiters.

#include <stdio.h>

main(int argc, char *argv[]) {
    FILE *fp, *ft;
    char ch;
    if (argc < 3) {
        printf("No file name given");
    }
    fp = fopen(argv[1], "r");
    ft = fopen(argv[2], "w");
    if (fp == NULL)
        printf("Opening error");
    if (ft == NULL)
        printf("Opening error");
    while (1) {
        ch = fgetc(fp);
        if (ch == EOF)
            break;
        if (ch == '/') {
            ch = fgetc(fp);
            if (ch == '*') {
                putc(' ', ft);
            }
        } else if (ch == '*') {
            ch = fgetc(fp);
            if (ch == '/') {
                putc(' ', ft);
            }
        } else {
            putc(ch, ft);
        }
    }
    fclose(fp);
    fclose(ft); 
}

Please help me to remove comment lines.

like image 952
Jinal Avatar asked Dec 06 '25 16:12

Jinal


1 Answers

There are multiple issues in your code:

  • the return type of main should not be omitted. Implicit int is obsolete and no longer allowed by the C Standard. The prototype should be int main(int argc, char *argv[])
  • if command line arguments were not passed to the program, it should exit after printing the error message, which should be output to stderr instead of stdout.
  • if the input file cannot be open, the program should not create the output file.
  • if either fopen failed, the program should stop instead of wandering into the realm of undefined behavior.
  • ch must have type int instead of char for the test (ch == EOF) to behave correctly.
  • you correctly identify the sequences /* and */ and replace them by a single , but it will actually remove all other occurrences of / and * and the subsequent character and you do not have any provisions for skipping the characters in between.
  • main should return 0.

Note also that your method might not identify comments correctly if the sequences /* or */ occur in single line comments or string or character constants. Furthermore, you should also handle escaped newlines (\ at the end of a line) as these may occur between the / and *, concealing the comment start or end sequences.

Here is a modified version that handles these cases:

#include <stdio.h>

/* read the next byte from the C source file, handing escaped newlines */
int getcpp(FILE *fp) {
    int ch;
    while ((ch = getc(fp)) == '\\') {
        if ((ch = getc(fp)) != '\n') {
            ungetc(ch, fp);
            return '\\';
        }
    }
    return ch;
}

/* read and write character and string constants */
int skipstr(int cch, FILE *fp, FILE *ft) {
    int ch;
    putc(cch, ft);
    while ((ch = getcpp(fp)) != EOF) {
        putc(ch, ft);
        if (ch == cch)
            return 0;
        if (ch == '\\') {
            if ((ch = getcpp(fp)) == EOF)
                return EOF;
            putc(ch, ft);
        }
    }
    return EOF;
}

int main(int argc, char *argv[]) {
    FILE *fp, *ft;
    int ch;

    if (argc < 3) {
        fprintf(stderr, "Missing arguments. Need input and output filenames\n");
        return 1;
    }
    if ((fp = fopen(argv[1], "r")) == NULL) {
        fprintf(stderr, "Cannot open input file %s\n", argv[1]);
        return 1;
    }
    if ((ft = fopen(argv[2], "w")) == NULL) {
        fprintf(stderr, "Cannot open output file %s\n", argv[2]);
        return 1;
    }
    while ((ch = getcpp(fp)) != EOF) {
        if (ch == '\'' || ch == '"') {
            if (skipstr(ch, fp, ft)) {
                fprintf(stderr, "unterminated string or character constant\n");
                break;
            }
            continue;
        }
        if (ch == '/') {
            if ((ch = getcpp(fp)) == '*') {
                /* multi-line comment */
                int lastc = 0;
                while ((ch = getcpp(fp)) != EOF) {
                    if (ch == '/' && lastc == '*') {
                        break;
                    }
                    lastc = ch;
                }
                if (ch == EOF) {
                    fprintf(stderr, "unterminated comment\n");
                    break;
                }
                ch = ' ';
            } else if (ch == '/') {
                /* single-line comment */
                while ((ch = getcpp(fp)) != EOF && ch != '\n')
                    continue;
                if (ch == EOF)
                    break;
            } else {
                putc('/', ft);
            }
        }
        putc(ch, ft);
    }
    fclose(fp);
    fclose(ft);
    return 0;
}
like image 157
chqrlie Avatar answered Dec 08 '25 09:12

chqrlie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!