C/C++ - Извлечение из текста нужной части

Ответить
Аватара пользователя
Alexey271

C/C++ - Извлечение из текста нужной части

Сообщение Alexey271 »

Доброго времени суток!

Я не работаю в С++, поэтому прошу вас помочь!



Задача состоит в том, что бы вытащить из текстового файла (*.txt) все значения (цифры) и сортировать их по колонкам (всего 4 колонки значений).

Прикладываю файл, который пытаюсь обработать.





C++ BUILDER:







Код:

Код: Выделить всё

// КОД МОЖНО И НЕ СМОТРЕТЬ
int max_i = ListBox1->Items->Count; // Колличество строк (отсчет с 1)
int i=0;
                for(i; i<max_i; i++)
                {
AnsiString str = ListBox1->Items->Strings[i]; //Заполняю строковую переменную
// значениями строк ListBox1
int a, b, c, d;
//ВЫТАСКИВАЕМ ПЕРВОЕ ЗНАЧЕНИЕ В СТРОКЕ
        a = StrToFloatDef(
str.SubString   (0,str.Pos(" ")),0);
str.Delete(1,str.Pos(" "));
//ВЫТАСКИВАЕМ ВТОРОЕ ЗНАЧЕНИЕ В СТРОКЕ
        b = StrToFloatDef(
str.SubString   (0,str.Pos(" ")),0);
str.Delete(1,str.Pos(" "));
//ВЫТАСКИВАЕМ ТРЕТЬЕ ЗНАЧЕНИЕ В СТРОКЕ
        c = StrToFloatDef(
str.SubString   (0,str.Pos(" ")),0);
str.Delete(1,str.Pos(" "));
//ВЫТАСКИВАЕМ ЧЕТВЕРТОЕ ЗНАЧЕНИЕ В СТРОКЕ
        d = StrToFloatDef(
str.SubString   (0,str.Length()),0);
ListBox5->Items->Add(d);
ListBox2->Items->Add(a);
ListBox3->Items->Add(b);
ListBox4->Items->Add(c);
str.Delete(1,str.Pos(" "));
                }  // конец цикла for
<!-- КОНЕЦ -->

// Да, знаю, что по идиотски сделано, но покоя не дает то, что он работает, если в строке первый символ является числом, а не пробелом
Аватара пользователя
Alexey271

Re: C/C++ - Извлечение из текста нужной части

Сообщение Alexey271 »

Блин, решил я конечно эту проблему, но хотелось бы узнать как можно вытаскивать значения, если не считать "пробелы" между числами?!

Есть идеи?



Текстовый фаил загружается в ListBox1



Код: Выделить всё

int max_i = ListBox1->Items->Count; // Считаю количество строк в загружаемом файле
int i;
    for(i=2; i<max_i; i++) // От 2, потому что первые  две строки (0 и 1) с "херней" 
    {
      AnsiString str = ListBox1->Items->Strings[i]; //Загружаю в переменную одну строку
      AnsiString a, b, c, d;
      str.Delete(1,6);
      a = str.SubString(0,str.Pos(" "));
      str.Delete(1,str.Pos(" "));
str.Delete(1,8);
b = str.SubString(0,str.Pos(" "));
str.Delete(1,str.Pos(" "));
str.Delete(1,6);
c = str.SubString(0,str.Pos(" "));
str.Delete(1,str.Pos(" "));
str.Delete(1,6);
d = str.SubString(0,str.Length());
str.Delete(1,str.Pos(" "));
}
Аватара пользователя
Alexey271

Re: C/C++ - Извлечение из текста нужной части

Сообщение Alexey271 »

Код:

Код: Выделить всё

void __fastcall TForm1::Button2Click(TObject *Sender)
{
ListBox1->Items->Count;  
int max_i = ListBox1->Items->Count;
AnsiString a, b, c, d;
int i;
                for(i=2; i<i<max_i; i++) 
                {
AnsiString str = ListBox1->Items->Strings[i];
str.Delete(1,6); //Удаляю лишние пробелы
int poitTozap = str.Pos("."); // рождаю переменную int и присваиваю ей порядковый номер первого найденного символа '.'
str.Delete( poitTozap, 1) ; // удаляю этот символ "точки"
str.Insert( ",", poitTozap); // заменяю на запятую (что бы потом переводить в float и запихивать в массив для расчетов и
 //построения графиков
a = str.SubString(0,str.Pos(" ")-1); // Загоняю в string a числа между 0 знаком и первым "пробелом"-1
str.Delete(1,str.Pos(" "));   // удаляю это строковое значение из string AnsiString str и повторяю операции с оставшимися в
 //строке символами
str.Delete(1,8);
poitTozap = str.Pos(".");
str.Delete( poitTozap, 1) ;
str.Insert( ",", poitTozap);
b = str.SubString(0,str.Pos(" ")-1);
str.Delete(1,str.Pos(" "));
str.Delete(1,6);
poitTozap = str.Pos(".");
str.Delete( poitTozap, 1) ;
str.Insert( ",", poitTozap);
c = str.SubString(0,str.Pos(" ")-1);
str.Delete(1,str.Pos(" "));
str.Delete(1,6);
poitTozap = str.Pos(".");
str.Delete( poitTozap, 1) ;
str.Insert( ",", poitTozap);
d = str.SubString(0,str.Length());
str.Delete(1,str.Pos(" "));
ListBox5->Items->Add(d);
ListBox2->Items->Add(a);
ListBox3->Items->Add(b);
ListBox4->Items->Add(c);
                }
}

Да, Все зашибись! Перегоняю каждый "столбец" в массив свой и "оло-ло", считай и строй графики!



ПРОБЛЕМА:

КАК БОЛЕЕ ГРАМОТНО РЕАЛИЗОВАТЬ ЭТОТ МЕТОД? (Я ПО ПОВОДУ ПРОБЕЛОВ В *.txt).
Аватара пользователя
Drongo

Re: C/C++ - Извлечение из текста нужной части

Сообщение Drongo »

Погоди, не спеши так. Изображение Давай ещё раз по порядку.



1. Грузим файл(который прикреплён) в ListBox

2. Из этого файла извлекаем четыре столбца в четыре ListBox'a? 1 стобец - 1 ListBox?

3. Удалить лишние пробелы между столбцами



P.S. Выполнил в билдере 6, ошибка, выход за границы диапазона.



Дай время, дня два-три, подумаю...
Аватара пользователя
Drongo

Re: C/C++ - Извлечение из текста нужной части

Сообщение Drongo »

Alexey271, Решил упрощённо, 15 строк кода. Изображение Я учитываю что в ListBox1 файл уже загружен.



Код: Выделить всё

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TSysCharSet chSplash;
   chSplash<<' ';
   TStringList *lst = new TStringList();
   TStringList *TokenList = new TStringList();
   lst->Text = ListBox1->Items->Text;
   for(int i = 2; i < lst->Count; i++){
      ExtractStrings(chSplash, chSplash, lst->Strings[i].c_str(), TokenList);
      ListBox2->Items->Add(TokenList->Strings[0]);
      ListBox3->Items->Add(TokenList->Strings[1]);
      ListBox4->Items->Add(TokenList->Strings[2]);
      ListBox5->Items->Add(TokenList->Strings[3]);
      TokenList->Clear();
     }
   delete lst;
   delete TokenList;
}
//---------------------------------------------------------------------------
Аватара пользователя
pva

Re: C/C++ - Извлечение из текста нужной части

Сообщение pva »

решение нисколько не лучше, просто сделанное по-другому, всё хранится в памяти:

Код: Выделить всё

// без этого билдер 4 не собирает STL
// #include <condefs.h>
// может понадобиться
// #include <vector>
// #include <algorithm>
// using namespace std;
vector<vector<double> > rows;
// считаем что в файле ровно 4 столбца, причём одинаковой длины
// иначе получится фигня
{
	ifstream input("20_1.txt");
	double x, y, tmp;
	input >> x >> y; // в начале файла 2 каких-то возможно нужных значения
	// читаем по спискам
	for(unsigned n = 0; (input >> tmp); n = (n + 1) & 3)
	{
		rows[n].push_back(tmp);
	}
	// сортируем списки
	for(unsigned n = 0; n < rows.size(); ++n)
	{	
		sort(rows[n].begin(), rows[n].end());
	}
}
Аватара пользователя
Alexey271

Re: C/C++ - Извлечение из текста нужной части

Сообщение Alexey271 »

Спасибо за варианты pva и Drongo!

Оттестирую ближе к вечеру по мск!



pva и Drongo еще один вопросик?!

В текстовом файле числа записаны через "точку", поэтому мне приходится находиться точку и заменять ее на "запятую" что бы смог применить StrToFloat!

Меня, честно говоря, это настораживает, потому что эти значения используются в расчетах. Ну просто нельзя так извращаться и писать код для извлечения чисел из файла на 2-3 стр.





Код:

Код: Выделить всё

...
int poitTozap = str.Pos("."); 
str.Delete( poitTozap, 1) ; 
str.Insert( ",", poitTozap); 
...
Аватара пользователя
Drongo

Re: C/C++ - Извлечение из текста нужной части

Сообщение Drongo »

Alexey271, Тогда можно так. Использовать StringReplace - искать точку и заменять её на запятую по всему тексту. Выделил зелёным цветом где написать строку.

Код: Выделить всё

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TSysCharSet chSplash;
   chSplash<<' ';
   TStringList *lst = new TStringList();
   TStringList *TokenList = new TStringList();
   lst->Text = ListBox1->Items->Text;
   lst->Text = StringReplace(lst->Text, ".", ",", TReplaceFlags()<<rfReplaceAll);
   for(int i = 2; i < lst->Count; i++){
      ExtractStrings(chSplash, chSplash, lst->Strings[i].c_str(), TokenList);
      ListBox2->Items->Add(TokenList->Strings[0]);
      ListBox3->Items->Add(TokenList->Strings[1]);
      ListBox4->Items->Add(TokenList->Strings[2]);
      ListBox5->Items->Add(TokenList->Strings[3]);
      TokenList->Clear();
     }
//   double *array = new double[ListBox2->Count];
   //for(int i = 0; i < ListBox2->Count; i++)
      //array[i] = ListBox2->Items->Strings[i].ToDouble();
   delete lst;
   delete TokenList;
}
//---------------------------------------------------------------------------
Аватара пользователя
pva

Re: C/C++ - Извлечение из текста нужной части

Сообщение pva »

Цитата Alexey271:



мне приходится находиться точку и заменять ее на "запятую"
C/C++ - Извлечение из текста нужной части




всё зависит от локали. StrToFloat использует локаль Windows, в которой у тебя настроена запятая. Зайди в панель управления, региональные настройки и поставь разделителем точку - тогда StrToFloat будет использовать точку. Оператор чтения из потока >> (если не переустанавливать локаль) использует локаль C++ по умолчанию, в которой используется точка. Как вариант, можно использовать сишную atof, которая использует локаль си, в которой тоже точка.



Код:

Код: Выделить всё

// c
//#include 
//#include 
double val = atof(TokenList->Strings[0].c_str());
// c++
//#include 
// using std::istringstream
double val = 0.0;
istringstream ss(TokenList->Strings[0].c_str());
ss >> val;
Аватара пользователя
Alexey271

Re: C/C++ - Извлечение из текста нужной части

Сообщение Alexey271 »

pva

Ух, буду иметь ввиду, спасибо
Ответить

Вернуться в «Программирование и базы данных»