Как я могу прочитать многострочный файл TXT с различными форматами в C? - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть входной текстовый файл, который выглядит примерно так:

1(1.230000e+00)
2(1.230000e+00)
(1.230000e+00 1.230000e+00)
3(1.230000e+00)
(1.230000e+00 1.230000e+00)
.
.
.

Я хочу иметь возможность читать каждую строку отдельно и различать их.Например, для первой строки я хочу сохранить 100 в одной переменной как int, а я хочу сохранить 1.230000e+00 в другой переменной как double.Вот что я пробовал:

fscanf(fp, "%d(%le)\n", &varInt, &varDouble);

Это работает для первой строки.Но как я могу выполнить цикл и сделать это для всех строк И также прочитать 3-ю строку, используя:

fscanf(fp, "(%le %le)\n", &varDouble1, &varDouble2);

Чтобы дать некоторый контекст, после прочтения каждой строки я выполню некоторую обработку, а затем прочту следующуюлиния.В зависимости от формата строки, я буду выполнять различные виды обработки.

Любая помощь приветствуется!Спасибо!

Ответы [ 3 ]

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

Если вы генерируете файл, добавьте префикс фиксированного размера для длины строки.Например, 016:1(1.230000e+00)\n.Затем прочитайте 4 байта с помощью fread, преобразуйте строку в int с помощью strtol и прочитайте остаток строки (\n входит в длину).Наконец разделите значения с помощью strtok( str, "( )" ).

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

fscanf (3) практически невозможно использовать, если вход строго не контролируется.Трудно отличить ошибки ввода-вывода от ошибок разбора.Вот почему гораздо чаще читать каждую строку с помощью fgets (3), а затем сканировать ее с помощью sscanf (3).

Поскольку sscanf возвращает количество проанализированных элементов, вы можете использовать это, чтобы определить, работает ли сканирование должным образом.Не нужно заглядывать во входные данные: если вы получили то, что ожидали, все готово, иначе попробуйте сканировать другим способом.Вот рабочий пример:

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

int
main( int argc, char *argv[] ) {
  if( argc < 2 ) {
    errx(EXIT_FAILURE, "syntax: %s filename", argv[0]);
  }

  FILE *input = fopen(argv[1], "r");
  if( !input ) {
    err(EXIT_FAILURE, "could not open '%s'", argv[0]);
  }

  static char line[128];
  int n;

  while( fgets(line, sizeof(line), input) != NULL ) {
    double d1, d2;
    int quantum;

    if( 2 == sscanf(line, "%d(%lf)", &quantum, &d1) ) {
      printf( "ok: %d\t%7.2f\n", 100 * quantum, d1 );
    } else if( 2 == sscanf(line, "(%lf %lf)", &d1, &d2) ) {
      printf( "ok: %7.2f\t%7.2f\n", d1, d2 );
    } else {
      printf( ">>> %s\n", line );
    }

  }

  if( !feof(input) ) {
    err(EXIT_FAILURE, "error reading %s", argv[1]);
  }

  return EXIT_SUCCESS;
}

Если вы обнаружите другие шаблоны, их легко добавить.Обратите внимание, что при сбое fgets программа возвращает успех, только если мы достигли конца файла.

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

Как уже упоминалось в комментариях, вы можете прочитать полную строку, а затем определить формат строки и соответственно проанализировать строку.Следующий код делает то, что вы хотите.Однако производительный код, вероятно, будет более надежно интерпретировать формат каждой строки.

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

char *GetStringNoBeginWhitespace( char *str )
{
    static const char whitespace[] = " \f\n\r\t\v";

    return(str + strspn(str, whitespace));
}

int main(int argc, char *argv[])
{
    char *line = NULL;
    FILE *fp;
    char buffer[255];

    int i;
    double d,d1;

    fp = fopen("data.txt", "r");

    while(fgets(buffer, 255, fp))
    {
        buffer[strlen(buffer)-1] = 0x00;
        line = GetStringNoBeginWhitespace( buffer );
        if( line )
        {
            fputs(line, stdout);
            if( isdigit((int)line[0] ))
            {
                printf("\tFormat is x(.......)\n");
                if( sscanf(line,"%d(%le)\n", &i, &d) == 2 )
                {
                    printf("      %d %le\n", i, d);
                }
                else
                {
                    printf("\tUnknown format....\n");
                }
            }
            else if( line[0] == '(' )
            {
                printf("\tFormat is ( ...... ....... )\n");
                if( sscanf(line, "(%le %le)\n", &d, &d1) == 2 )
                {
                    printf("      %le %le\n", d, d1);
                }
                else
                {
                    printf("\tUnknown format....\n");
                }
            }
            else
            {
                printf("\tUnknown format....\n");
            }
        }
    }

    fclose(fp); 
    return(0);
}

Вывод:

jnorton@ubuntu:~/source$ ./a.out 
1(1.230000e+00) Format is x(.......)
      1 1.230000e+00
2(1.230000e+00) Format is x(.......)
      2 1.230000e+00
(1.230000e+00 1.230000e+00) Format is ( ...... ....... )
      1.230000e+00 1.230000e+00
3(1.230000e+00) Format is x(.......)
      3 1.230000e+00
(1.230000e+00 1.230000e+00) Format is ( ...... ....... )
      1.230000e+00 1.230000e+00

файл data.txt:

1(1.230000e+00)
2(1.230000e+00)
(1.230000e+00 1.230000e+00)
3(1.230000e+00)
(1.230000e+00 1.230000e+00)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...