Как я могу обнаружить незавершенный комментарий и написать сообщение об ошибке «Ошибка: строка X: незавершенный комментарий» в стандартный поток ошибок в моем коде? - PullRequest
0 голосов
/ 24 февраля 2019
#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

1 Ответ

0 голосов
/ 24 февраля 2019

Вы можете изменить функцию m_cmnt() для вывода сообщения об ошибке, если при поиске */: *1003*:

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");
}

выдается сообщение об ошибке, вы должны сохранитьотслеживание количества строк везде.

Обратите также внимание, что вы должны также обрабатывать // комментариев и более точно анализировать строки, обрабатывая escape-последовательности.

Вот версия с обработкой номера строки:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...