Как пропустить комментарий в программировании на c с помощью fopen - PullRequest
0 голосов
/ 20 мая 2019

Я хочу игнорировать / пропустить комментарии в текстовом файле, когда я использую fgets.

Проблема в том, что я могу пропустить комментарий, только если первый символ в строке начинается с #.Комментарии начинаются с # в моем текстовом файле.Но в моем file.txt есть некоторые #, которые не являются первым символом строки, например:

#Paths
A B #Path between A and B.
D C #Path between C and D.

A - мой первый узел, B - мой второй узел, и когда # приходит, яхотите игнорировать остальную часть текста до следующей строки.Мой новый узел должен быть D и C и т. Д. Я могу использовать только «r» в функции fopen.Я пробовал fgets, но он читает построчно, и fgetc тоже не помогает.

    bool ignore_comments(const char *s)
    {
        int i = 0;
        while (s[i] && isspace(s[i])) i++;
        return (i >= 0 && s[i] == '#');
    }
    FILE *file;
    char ch[BUFSIZE];
    file = fopen("e.txt", "r");
    if (file == NULL) {
        printf("Error\n");
        fprintf(stderr, "ERROR: No file input\n");
        exit(EXIT_FAILURE);
    }
    while(fgets(ch, BUFSIZE, file) != NULL)
    {
              if (line_is_comment(ch)) {
                        // Ignore comment lines.
                        continue;
                printf("%c",*ch);
                }
     fscanf(file, "%40[0-9a-zA-Z]s", ch);
....
}

Ответы [ 3 ]

1 голос
/ 20 мая 2019

Также имена методов разные, но я прав с этой версией?Не обращайте внимания на мой грязный метод line_is_comment - начиная с первой версии, если только вы не хотите играть; -)

Расширенный тестовый ввод:

#Paths
A B #Path between A and B.
D C #Path between C and D.
E F
G H

Вывод:

 rest of line read
AB rest of line read
DC rest of line read
EF rest of line read
GH rest of line read
#include <stdio.h>

bool line_is_comment(const char *s)
{
    char *commentPos = const_cast<char*>(strchr(s, '#'));
    if(commentPos != NULL) {
        *commentPos = 0; // cut-off chars after comment
        //return true; // or false then to accept the line
        return commentPos == s;
    }
    return false;
}

#define BUFSIZE 50

int main()
{
    FILE *file;
    char ch[BUFSIZE];
    file = fopen("e.txt", "r");
    if (file == NULL) {
        printf("Error\n");
        fprintf(stderr, "ERROR: No file input\n");
        exit(EXIT_FAILURE);
    }
    int x;
    while(!feof(file)) {
        x = fscanf(file, "%40[0-9a-zA-Z]s", ch);
        if(x == 0) {
            ch[0] = fgetc(file);
            if(ch[0] == '#' || ch[0] == '\n') {
                if(ch[0] != '\n') fgets(ch, BUFSIZE, file);
                printf(" rest of line read\n");
            }
        } else if(x<0) break;
        else {
                 printf("%c",*ch); // continue with ... undisclosed part here
            }
    }

    return 0;
}
0 голосов
/ 21 мая 2019

Вы также можете использовать strcspn, чтобы обрезать все комментарии (и, если их нет, обрезать окончания строк из вашего буфера) за один простой вызов. Где вы обычно обрезаете конец строки из буфера, считанного fgets() с помощью:

        ch[strcspn (ch, "\r\n")] = 0;  /* trim line-ending */

Вы можете просто добавить символ "#" в список reject и nul-terminate там, если есть комментарий. Это уменьшило бы полную задачу удаления комментариев, начинающихся с '#' и вывода новой отформатированной строки:

    while (fgets (ch, BUFSIZE, fp)) {   /* read every line */
        ch[strcspn (ch, "#\r\n")] = 0;  /* trim comment or line-ending */
        puts (ch);                      /* output line w/o comment */
    }

Короткий пример, в котором файл читается как первый аргумент программы (или читается из stdin по умолчанию, если аргумент не указан), вы можете сделать:

#include <stdio.h>
#include <string.h>

#define BUFSIZE 1024    /* if you need a constant, #define one (or more) */

int main (int argc, char **argv) {

    char ch[BUFSIZE];
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    while (fgets (ch, BUFSIZE, fp)) {   /* read every line */
        ch[strcspn (ch, "#\r\n")] = 0;  /* trim comment or line-ending */
        puts (ch);                      /* output line w/o comment */
    }

    if (fp != stdin) fclose (fp);       /* close file if not stdin */

    return 0;
}

Пример входного файла

Заимствование файла примера Тома :)

$ cat dat/comments_file.txt
#Paths
A B #Path between A and B.
D C #Path between C and D.
E F
G H

Пример использования / Вывод

$ ./bin/comments_remove <dat/comments_file.txt

A B
D C
E F
G H

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 21 мая 2019

следующий предложенный код:

  1. выполняет желаемую функциональность
  2. чисто компилирует
  3. правильно проверяет наличие ошибок
  4. в этом ответе используется конечный автомат на основе: 'InComment'

и теперь предложенный код:

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
    int InComment = 0;

    FILE *fp = fopen( "file.txt", "r" );
    if( !fp )
    {
        perror( "fopen to read -file.txt- failed" );
        exit( EXIT_FAILURE );
    }

    int ch;

    while( (ch = fgetc(fp)) != EOF )
    {
        if( ch == '#' )
        {
            InComment = 1;
        }

        else if( ch == '\n' )
        {
            InComment = 0;
            fputc( ch, stdout );
        }

        else if( !InComment )
        {
            fputc( ch, stdout );
        }
    }
    fclose( fp );
}
...