Показать полную графическую версию : Извлечение из текста нужной части
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).
Погоди, не спеши так. :) Давай ещё раз по порядку.
1. Грузим файл(который прикреплён) в ListBox
2. Из этого файла извлекаем четыре столбца в четыре ListBox'a? 1 стобец - 1 ListBox?
3. Удалить лишние пробелы между столбцами
P.S. Выполнил в билдере 6, ошибка, выход за границы диапазона.
Дай время, дня два-три, подумаю...
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;
}
//---------------------------------------------------------------------------
решение нисколько не лучше, просто сделанное по-другому, всё хранится в памяти:
// без этого билдер 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);
...
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;
}
//---------------------------------------------------------------------------
мне приходится находиться точку и заменять ее на "запятую" »
всё зависит от локали. 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
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.