Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Обработчик строк из текстового файла (http://forum.oszone.net/showthread.php?t=317428)

pageYK@fb 02-08-2016 16:37 2656196

Обработчик строк из текстового файла
 
Есть файл с текстом формата(разделитель '|'):

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 2656506

pageYK@fb, в чем возникла проблема?
Где рассуждения?

Iska 03-08-2016 14:50 2656511

lxa85, «рассуждения» были здесь: CMD/BAT - [решено] обработка в подстроке.

pageYK@fb 03-08-2016 17:47 2656576

lxa85, рассуждениями поделились ссылочкой выше.
А так затык, в основном, как в Delphi индентифицировать в строке это третье число, delimited опробовал, не зашло.

Iska 03-08-2016 18:44 2656595

Цитата:

Цитата pageYK@fb
delimited опробовал, не зашло. »

Ну, так показывайте, как именно опробовали.

shisik 03-08-2016 19:28 2656608

Цитата:

Цитата pageYK@fb
А так затык, в основном, как в 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 2656684

Вся "работа" вокруг анализа одной "колонки"... не нужно что-то выдумывать. Для выделения подстроки в Delphi все есть
ExtractStrings
Код:

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;

Delimiter
Код:

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 2656856

Из вышестоящего, собрал вот такой кусок:

Код:

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 2656870

Цитата:

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

Разве методов TStringList (add, insert, delete и прочих, для выполнения задачи, не хватает? Вариантов много, можно вообще все сделать в TSL (например, копирование нужной строки в конец списка add() с заменой подстроки StringReplace) и сохранением в файл SavetoFile.

pageYK@fb 08-08-2016 11:03 2657791

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 2657802

Цитата:

Цитата pageYK@fb
Методов хватает, работает не так как надо. »

Инструментов под рукой нет, но на вскидку - вы же заперли сохранение в цикл вычислений
Код:

while value>394 do
        begin
          ...
          ...
          ??? ts.SaveToFile('2.txt');
        end;

да и никто вас не ограничивает работой с одним списком?

pageYK@fb 08-08-2016 14:36 2657849

opel431,
Проблема заключается в том, что делиметр разделяет строку на подстроки, а как обратно конкатенировать для записи в файл непонятно.

lxa85 08-08-2016 15:13 2657857

pageYK@fb, есть строка, разбитая на под строки.
Что вам мешает собрать ее обратно?
Если у вас формат файла фиксирован, то и собирайте в цикле
Код:

str = "";
for i = 1 to n do
    str = str+"|"+delimiters[i];

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

Iska 08-08-2016 15:48 2657865

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

pageYK@fb 08-08-2016 15:58 2657867

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

lxa85 08-08-2016 16:48 2657874

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

opel431 08-08-2016 19:54 2657926

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

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

SplitString+
Код:

......
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 2658799

opel431,
Спасибо за splitstring, а memo работает только на кнопке, была бы привязка к форме. Спасибо, и на этом.

opel431 11-08-2016 13:40 2658818

Цитата:

Цитата pageYK@fb
а memo работает только на кнопке »

Форма имеет достаточно обработчиков событий для решения ваших желаний.


Время: 22:31.

Время: 22:31.
© OSzone.net 2001-