Войти

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


pageYK@fb
02-08-2016, 16:37
Есть файл с текстом формата(разделитель '|'):

1|325230ш5ш3|438|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|
2|32523лпукп4|22|Европа|ДУБЛИН, ИРЛАНДИЯ|
3|32епкупщ4пп|21|Венгрия|БУДАПЕШТ, ВЕНГРИЯ|

Нужно пропарсить его
(
1. Если в 3-ем числе >394, то вычитаем из него 394(строку дублируем),остаток оставляем новой строкой.(учесть, что операция должна быть циклична, т.к. встречаются числа больше 792)
2. Отсортировать строки по 3-ему числу. (1-ое число - счетчик)
)
, чтобы на выходе получилось это:

1|32епкупщ4пп|21|Венгрия|БУДАПЕШТ, ВЕНГРИЯ|
2|32523лпукп4|22|Европа|ДУБЛИН, ИРЛАНДИЯ|
3|325230ш5ш3|46|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|
4|325230ш5ш3|394|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|

lxa85
03-08-2016, 14:31
pageYK@fb, в чем возникла проблема?
Где рассуждения?

Iska
03-08-2016, 14:50
lxa85, «рассуждения» были здесь: CMD/BAT - [решено] обработка в подстроке (http://forum.oszone.net/thread-317218.html).

pageYK@fb
03-08-2016, 17:47
lxa85, рассуждениями поделились ссылочкой выше.
А так затык, в основном, как в Delphi индентифицировать в строке это третье число, delimited опробовал, не зашло.

Iska
03-08-2016, 18:44
delimited опробовал, не зашло. »
Ну, так показывайте, как именно опробовали.

shisik
03-08-2016, 19:28
А так затык, в основном, как в Delphi индентифицировать в строке это третье число, delimited опробовал, не зашло. »

А что если написать функцию разделения строки по типу питоновской split или пхпшной explode? Примерно так:

function split(splitter: Char; str: String): TStringList;
var substr: String;
var parts: TStringList;
var i: Integer;
begin
parts := TStringList.Create;
for i := 1 to Length(str) do
begin
if str[i] = splitter then
begin
parts.add(substr);
substr := '';
end else
substr := substr + str[i];
end;
parts.add(substr);
result := parts;
end;

Соответственно, на выходе имеем TStringList, где третье число - parts[2]. Ну а дальше в Integer преобразовать проще простого:


var value: Integer;

...

value := StrToInt(parts[2]);


P.S. 100 лет не писал на Delphi, уж простите, если накосячил.

opel431
03-08-2016, 23:00
Вся "работа" вокруг анализа одной "колонки"... не нужно что-то выдумывать. Для выделения подстроки в Delphi все есть
const
str = '1|325230ш5ш3|438|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|'; // для примера одна строка
var
sl: TStringList;
begin
sl := TStringList.Create;
begin
try
ExtractStrings(['|', ','], [' '], str, sl); // Note: ExtractStrings does not add empty strings to the list.
ShowMessage(sl[2]);
finally
sl.Free;
end;
end;const
str = '1|325230ш5ш3|438|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|';
var
i: Integer;
begin
with TStringList.Create do
begin
Delimiter := '|';
StrictDelimiter := True;
DelimitedText := str;
{for i := 0 to Count - 1 do
ShowMessage(Strings[i]);}
ShowMessage(Strings[2]);
Free;
end;все остальные действия от обработки результата.

pageYK@fb
04-08-2016, 14:24
Из вышестоящего, собрал вот такой кусок:


var
i,l:integer;
ts:TStringList;
s: string;

begin

ts := TStringList.Create;

try
ts.LoadFromFile('1.txt');
Delimiter := '|';
StrictDelimiter := True;
DelimitedText := ts;
for l:=0 to ts.Count-1 do
begin

value := StrToInt(ts.Strings[2]);
while value>394 do
begin
value := value-394;
ts.Strings[2]:=IntToStr('394');
// Как передать обновленную строку в файл?
end;
ts.Strings[2]:=IntToStr(value);
// передача строки в файл с остатком.
end;
// сортировка

finally
ts.Free;
end;

end.

Как прописать запись строки в файл из цикла, через append?

opel431
04-08-2016, 15:27
Как прописать запись строки в файл из цикла, через append? »Разве методов TStringList (add, insert, delete и прочих, для выполнения задачи, не хватает? Вариантов много, можно вообще все сделать в TSL (например, копирование нужной строки в конец списка add() с заменой подстроки StringReplace) и сохранением в файл SavetoFile.

pageYK@fb
08-08-2016, 11:03
opel431, Методов хватает, работает не так как надо.
var
i,l,value:integer;
ts:TStringList;
s: string;

begin ts := TStringList.Create;

try
ts.LoadFromFile('1.txt');
ts.Delimiter := '|';
for l:=0 to ts.Count-1 do
begin
ts.DelimitedText := ts.Strings[l];
value := StrToInt(ts.Strings[2]);
while value>394 do
begin
value := value-394;
ts.Strings[2]:='394';
ts.SaveToFile('2.txt');
end;

end;

finally
ts.Free;
end;
SaveToFile по итогу, возвращает в файл текст уже разбитый на подстроки:
"1
325230ш5ш3
438
Лондон
ЛОНДОН,
ВЕЛИКОБРИТАНИЯ".

И как оперировать с несколькими строками для их сортировки так мне осталось неясным.

opel431
08-08-2016, 11:49
Методов хватает, работает не так как надо. »Инструментов под рукой нет, но на вскидку - вы же заперли сохранение в цикл вычислений
while value>394 do
begin
...
...
??? ts.SaveToFile('2.txt');
end;
да и никто вас не ограничивает работой с одним списком?

pageYK@fb
08-08-2016, 14:36
opel431,
Проблема заключается в том, что делиметр разделяет строку на подстроки, а как обратно конкатенировать для записи в файл непонятно.

lxa85
08-08-2016, 15:13
pageYK@fb, есть строка, разбитая на под строки.
Что вам мешает собрать ее обратно?
Если у вас формат файла фиксирован, то и собирайте в цикле
str = "";
for i = 1 to n do
str = str+"|"+delimiters[i];

Соотв n - кол-во частей строк
delimiters - полученный "конструктор" подстрочек
str - результирующая строка

Iska
08-08-2016, 15:48
opel431, lxa85, а какого-нибудь аналога basic'овского «Join()» в Delphi нету разве?

pageYK@fb
08-08-2016, 15:58
lxa85, opel431,
Строки разбиваются (при delimiter = "|") на отделяемое запятыми тоже, поэтому обратно приведенным вами способом не соберешь.
Вот почему мне не нравится этот метод через делимитедтекст.
Поэтому прошу выкладывать решение, а не функцию которую можно применить.(уже n-раз выходит, что возникают только доп.вопросы)

lxa85
08-08-2016, 16:48
Iska, честно, не знаю :)
pageYK@fb, что значит "не соберешь"?
Что отладчик говорит? Что говорят watchdog'и?
Что в полученных структурах, что на выходе?
Вы хоть какую-то информацию к размышлениям давайте.

opel431
08-08-2016, 19:54
Встроенного аналога, с параметром разделителя, не нашел (есть обычная Concat), заменяющая +. Так что, или ее или ручками.
pageYK@fb, нужно с интересом подходить к своей задаче. Поковыряюсь параллельно с вами.

Поставил триальный XE4, нашел в справочнике функцию SplitString (функция есть, как минимум с XE) и .... Для наглядность, применил TMemo.
pageYK@fb, дальнейшие "телодвижения" (сортировка, адаптация, оптимизация и все, что вам требуется, делайте сами).


......
var
Form1: TForm1;
ts: TStringList;
......

procedure TForm1.Button1Click(Sender: TObject);
var
i, n, value: integer;
begin
if FileExists(ExtractFilePath(Application.ExeName) + '1.txt') then
begin
ts := TStringList.Create;

try
ts.LoadFromFile(ExtractFilePath(Application.ExeName) +'1.txt');

for i := 0 to ts.Count - 1 do
begin
value := StrToInt((SplitString(ts.Strings[i], '|')[2]));
n := StrToInt(SplitString(ts.Strings[i], '|')[0]);

if value > 394 then
Memo1.Lines.Add(IntToStr(n) + '|' + (SplitString(ts.Strings[i], '|')[1])
+ '|' + IntToStr(value) + '|' + (SplitString(ts.Strings[i], '|')[3]) +
'|' + (SplitString(ts.Strings[i], '|')[4]) + '|');

while value > 394 do
begin
value := value - 394;
end;
n := StrToInt(SplitString(ts.Strings[i], '|')[0]) + 1;
Memo1.Lines.Add(IntToStr(n) + '|' + (SplitString(ts.Strings[i], '|')[1]) +
'|' + IntToStr(value) + '|' + (SplitString(ts.Strings[i], '|')[3]) + '|'
+ (SplitString(ts.Strings[i], '|')[4]) + '|');
end;

finally
Memo1.Lines.SaveToFile(ExtractFilePath(Application.ExeName) +'2.txt');
FreeAndNil(ts);
end;
end;
end;Результат
1|325230ш5ш3|438|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|
2|325230ш5ш3|44|Лондон|ЛОНДОН, ВЕЛИКОБРИТАНИЯ|
3|32523лпукп4|22|Европа|ДУБЛИН, ИРЛАНДИЯ|
4|32епкупщ4пп|21|Венгрия|БУДАПЕШТ, ВЕНГРИЯ|

pageYK@fb
11-08-2016, 12:22
opel431,
Спасибо за splitstring, а memo работает только на кнопке, была бы привязка к форме. Спасибо, и на этом.

opel431
11-08-2016, 13:40
а memo работает только на кнопке »Форма имеет достаточно обработчиков событий для решения ваших желаний.




© OSzone.net 2001-2012