LINUX.ORG.RU

С: ввод данных в структуру из неворматированного текста.


0

0

Задача такая: есть текстовый файл, в который в произвольном порядке идет
вывод программы. Среди этого текста (известно в каком месте) идут строки
типа:

A1 B1 C1 D1
A2 B2 C2 D2
...........
An Bn Cn Dn

Причем n _заранее неизвестно_.
Требуется: _за один проход_ считать эти строки в структуру типа

struct {
	type A, B, C, D;
}

Так вот: самое главное - за один проход чтения. Как это сделать?
Я программист неопытный, но думаю что проще всего с помощью динамически
образуемого связного списка...
Заранее всем спасибо.
★★

Да, конечно считать в массив...

octy ★★
() автор топика

Критично именно С или С++ можно?
Кроме того, есть еще flex

На плюсах это делается обычно так:

#include <iostream>

class Type{
public:
friend std::istream& operator>>(std::istream&, Type&);
};

std::istream& operator>>(std::istream& istr, Type& obj){

// чтение данных из потока
return istr;
}

// собственно чтение; N - сколько экземпляров прочитать

typedef std::vector<Type> TypeList;
std::ifstream istr("MyDataFile");
TypeList objects;
for(int i = 0; i < N; ++i){
Type obj; istr >> obj; objects.push_back(obj);
}

Кроме того, если текст действительно неформатированный, ноимеет конкретную структуру, то используют спец средства типа flex+bison
или pccts

Flogger_d
()
Ответ на: комментарий от Flogger_d

2Flogger_d

К тому же как я понимаю, в примере N должно быть известно заранее, если бы было так, то не было бы проблемы.

octy ★★
() автор топика

Кажется, чего-то получилось... Но не уверен, что это очень красиво.

typedef struct cl {
  char data[81];
  struct cl *next;
} str0;

typedef struct {
  int name;
  float x,y,z;
} str1;


unsigned int el_num=0;
str0 * firstp=NULL;
str0 * nextp=firstp;
str0 * a;
char bfr[81];

str1 * arr;

/* Позиционирование на первую нужную строку */
..............................................


/* Считывание */ 

while (fgets (bfr, 80, handle)){
  if (strstr (bfr,"END") )
    break;
  a=(str0 *) malloc (sizeof (str0));
  strncpy(a->data, bfr, 81);
  a->next=NULL;
  if (!firstp){
    firstp=a;
    nextp=firstp;
  }
  else {
    nextp->next=a;
    nextp=a;
  }
  el_num++;
}

/* Заполнение требуемого массива */
arr=(str1 *) malloc (el_num*sizeof(str1));
nextp=firstp;
a=nextp;
for (i=0; i<el_num; i++){

 /* Заполнение arr[i].name; arr[i].x ... */

a=a->next;
}

/*Освобождение связного списка */
nextp=firstp;
a=nextp->next;
do { a=nextp->next; free (nextp); nextp=a; } while (a);


/*================================================================*/

Только вот возник еще тупой вопрос (если никто не ответит, вынесу в отделеный топик :-@ ):
Как уже имея строку типа
char * blabla= "12 18.4 27.8 -11.3"

выделить из нее значения int , float x3? 
Извините, наверное совсем туплю.

anonymous
()
Ответ на: комментарий от anonymous

#include <stdio.h>

const char s[] = "12 18.4 27.8 -11.3";

main()
{
    int i;
    float d1, d2, d3;

    sscanf(s, "%d %f %f %f", &i, &d1, &d2, &d3);

    printf("%d %.1f %.1f %.1f\n", i, d1, d2, d3);

    return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

Премного благодарствую, пора спать наверное...

А как насчет моего метода ;)

octy ★★
() автор топика
Ответ на: комментарий от anonymous

Выделить из строки

> Только вот возник еще тупой вопрос (если никто не ответит, вынесу в отделеный топик :-@ ): > Как уже имея строку типа > char * blabla= "12 18.4 27.8 -11.3"

> выделить из нее значения int , float x3?

Если заканее известно, сколько чисел и где какие (int, float) стоят, то можно попробовать sscanf.

Иначе -- выделять группы идущих подряд непробельных символов и преобразовывать каждую группу тем же sscanf или atoi/atof.

-----------------------------

Корольков Дмитрий

http://dkorolkov.by.ru

DKorolkov
()
Ответ на: Выделить из строки от DKorolkov

А я в свое время игрался с конструкцией %* в форматной строке.
См man на scanf. Звездочка означает что данное поле нужно пропустить.
Так что
char buf[1024]; // Заложимся на разумные значения
int dummy,i;
int count=0;
do{
++count;
for(i = 0; i < count-1;++i) strcat(buf,"%*d ");
strcat(buf,"%d");
}while(sscanf(text,buf,&dummy) != 1);

Соответственно - после цикла в count будет количество чисел.
Точно также можно последовательно считать

Flogger_d
()
Ответ на: комментарий от Flogger_d

Опять таки - НАСТОЯТЕЛЬНО рекомендую внимательно посмотреть в сторону flex

Flogger_d
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.