Войти

Показать полную графическую версию : Извлечение из текста нужной части


Alexey271
21-11-2010, 16:52
Доброго времени суток!
Я не работаю в С++, поэтому прошу вас помочь!

Задача состоит в том, что бы вытащить из текстового файла (*.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
21-11-2010, 18:48
Блин, решил я конечно эту проблему, но хотелось бы узнать как можно вытаскивать значения, если не считать "пробелы" между числами?!
Есть идеи?

Текстовый фаил загружается в 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
21-11-2010, 23:23
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
22-11-2010, 17:25
Погоди, не спеши так. :) Давай ещё раз по порядку.

1. Грузим файл(который прикреплён) в ListBox
2. Из этого файла извлекаем четыре столбца в четыре ListBox'a? 1 стобец - 1 ListBox?
3. Удалить лишние пробелы между столбцами

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

Дай время, дня два-три, подумаю...

Drongo
22-11-2010, 17:48
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
22-11-2010, 19:50
решение нисколько не лучше, просто сделанное по-другому, всё хранится в памяти:

// без этого билдер 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
23-11-2010, 03:50
Спасибо за варианты pva и Drongo!
Оттестирую ближе к вечеру по мск!

pva и Drongo еще один вопросик?!
В текстовом файле числа записаны через "точку", поэтому мне приходится находиться точку и заменять ее на "запятую" что бы смог применить StrToFloat!
Меня, честно говоря, это настораживает, потому что эти значения используются в расчетах. Ну просто нельзя так извращаться и писать код для извлечения чисел из файла на 2-3 стр.

...
int poitTozap = str.Pos(".");
str.Delete( poitTozap, 1) ;
str.Insert( ",", poitTozap);
...

Drongo
23-11-2010, 14:04
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
24-11-2010, 20:26
мне приходится находиться точку и заменять ее на "запятую" »
всё зависит от локали. StrToFloat использует локаль Windows, в которой у тебя настроена запятая. Зайди в панель управления, региональные настройки и поставь разделителем точку - тогда StrToFloat будет использовать точку. Оператор чтения из потока >> (если не переустанавливать локаль) использует локаль C++ по умолчанию, в которой используется точка. Как вариант, можно использовать сишную atof, которая использует локаль си, в которой тоже точка.

// c
//#include <stdlib.h>
//#include <math.h>
double val = atof(TokenList->Strings[0].c_str());

// c++
//#include <sstream>
// using std::istringstream

double val = 0.0;
istringstream ss(TokenList->Strings[0].c_str());
ss >> val;

Alexey271
25-11-2010, 13:19
pva
Ух, буду иметь ввиду, спасибо




© OSzone.net 2001-2012