Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение из строки имени и значений параметров / 10 сообщений из 10, страница 1 из 1
28.09.2018, 19:10
    #39710100
Martin114
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Стоит такая задача:
На входе задана строка, где задано название параметра и ряд его значений, разделенные пробелами (и может быть знаками табуляции) (в данном примере их 5, но может быть произвольным), на выходе - массив с именем параметра и его значениями (можно в виде строк, в числа я потом преобразую):

Пример 1:
readStr = 'Названиепарам1 -0.013 0.017 0.099 0.189 0.221*'

На выходе должно быть:
paramValues[0] = 'Названиепарам1'
paramValues[1] = '-0.013'
paramValues[2] = '0.017'
paramValues[3] = '0.099'
paramValues[4] = '0.189'
paramValues[5] = '0.221*'

Пример 2:
readStr = 'Paramname 1.691 1.764 1.829 2.007* 1.916'

На выходе должно быть:
paramValues[0] = 'Paramname'
paramValues[1] = '1.691'
paramValues[2] = '1.764'
paramValues[3] = '1.829'
paramValues[4] = '2.007*'
paramValues[5] = '1.916'

Наваял, исходя из опыта предшественников, работавшим над проектом, следующую процедуру:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
procedure GetParametersShortProtocolValues(var paramValues: array of variant;
    const readStr: String);
var
    i: Integer;
    M: TMatchCollection;
    REx: TRegEx;
begin
    REx := TRegEx.Create('([a-zA-Z0-9.*-+]+)', [roIgnoreCase]);
 
    if REx.IsMatch(readStr) then
    begin
        M := REx.Matches(readStr); // получаем коллекцию совпадений
    SetLength(paramValues, M.Item[0].Groups.Count + 1); // выдает ошибку несоответствия типов
        paramValues[0] := M.Item[0].Groups[1].value;
        for i := 1 to min(M.Item[0].Groups.Count - 1, Length(paramValues) - 1) do // Вообще не заполняет массив paramValues значениями из M
            paramValues[i - 1] := M.Item[0].Groups[i].value;
    end;
end;



но получил некомпиляцию из-за ошибки несоответствия типов. В случае, когда я жестко задал SetLength(paramValues, 5), paramValues[0] присвоилось M.Item[0].Groups[1].value, но в цикле ничего не присвоилось.
...
Рейтинг: 0 / 0
28.09.2018, 21:32
    #39710140
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, Variants;

function ParseArgs(const str: string): TArray<Variant>;
var
  i, valueInteger: Integer;
  Arr: TArray<string>;
  Value: string;
  valueExtended: Extended;
  delm: char;
begin
  delm := FormatSettings.DecimalSeparator;
  FormatSettings.DecimalSeparator := '.';

  Arr := str.Split([' ']);
  SetLength(Result, Length(Arr));
  for i := Low(Arr) to High(Arr) do
  begin
    Value := Arr[i];
    if TryStrToInt(Value, valueInteger) then
      Result[i] := valueInteger
    else if TryStrToFloat(Value, valueExtended, FormatSettings) then
      Result[i] := valueExtended
    else
      Result[i] := Value;
  end;
  FormatSettings.DecimalSeparator := delm;
end;

var
  v: TArray<Variant>;
  i: Integer;

begin
  try
    v := ParseArgs('Paramname 5 1.691 1.764 1.829 2.007* 1.916');
    for i := Low(v) to High(v) do
    begin
      Writeln(VarToStr(v[i]), ' : ', VarTypeAsText(VarType(v[i])));
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Код: sql
1.
2.
3.
4.
5.
6.
7.
Paramname : UnicodeString
5 : Integer
1,691 : Double
1,764 : Double
1,829 : Double
2.007* : UnicodeString
1,916 : Double
...
Рейтинг: 0 / 0
28.09.2018, 22:00
    #39710145
чччД__
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Martin114,

offtopic: а если в качестве параметра понадобится передавать строку с пробелом (табуляцией)?

Посмотри, как GetParamStr() модуля System.pas сделано, там отдельные параметры могут быть квотированы двойной ковычкой, хотя, конечно, дело твое:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
function GetNextParam(P: PChar; var Param: string): PChar;
// Как в GetParamStr() из System.pas
var
  i, Len: Integer;
  Start, S, Q: PChar;
begin
  while True do
  begin
    while (P[0] <> #0) and (P[0] <= ' ') do
      P := CharNext(P);
    if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
  end;
  Len := 0;
  Start := P;
  while P[0] > ' ' do
  begin
    if P[0] = '"' then
    begin
      P := CharNext(P);
      while (P[0] <> #0) and (P[0] <> '"') do
      begin
        Q := CharNext(P);
        Inc(Len, Q - P);
        P := Q;
      end;
      if P[0] <> #0 then
        P := CharNext(P);
    end
    else
    begin
      Q := CharNext(P);
      Inc(Len, Q - P);
      P := Q;
    end;
  end;

  SetLength(Param, Len);

  P := Start;
  S := Pointer(Param);
  i := 0;
  while P[0] > ' ' do
  begin
    if P[0] = '"' then
    begin
      P := CharNext(P);
      while (P[0] <> #0) and (P[0] <> '"') do
      begin
        Q := CharNext(P);
        while P < Q do
        begin
          S[i] := P^;
          Inc(P);
          Inc(i);
        end;
      end;
      if P[0] <> #0 then P := CharNext(P);
    end
    else
    begin
      Q := CharNext(P);
      while P < Q do
      begin
        S[i] := P^;
        Inc(P);
        Inc(i);
      end;
    end;
  end;

  Result := P;
end;

function GetParamByIndex(apCommandLine: PChar; index: Integer): string;
begin
  while True do
  begin
    apCommandLine := GetNextParam(apCommandLine, Result);
    if (Index = 0) or (Result = '') then Break;
    Dec(Index);
  end;
end;

...
Рейтинг: 0 / 0
28.09.2018, 22:07
    #39710147
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Martin114Стоит такая задача:
На входе задана строка, где задано название параметра и ряд его значений, разделенные пробелами (и может быть знаками табуляции) (в данном примере их 5, но может быть произвольным), на выходе - массив с именем параметра и его значениями (можно в виде строк, в числа я потом преобразую):

Пример 1:
readStr = 'Названиепарам1 -0.013 0.017 0.099 0.189 0.221*'

На выходе должно быть:
paramValues[0] = 'Названиепарам1'
paramValues[1] = '-0.013'
paramValues[2] = '0.017'
paramValues[3] = '0.099'
paramValues[4] = '0.189'
paramValues[5] = '0.221*'

Пример 2:
readStr = 'Paramname 1.691 1.764 1.829 2.007* 1.916'

На выходе должно быть:
paramValues[0] = 'Paramname'
paramValues[1] = '1.691'
paramValues[2] = '1.764'
paramValues[3] = '1.829'
paramValues[4] = '2.007*'
paramValues[5] = '1.916'


как вариант, самый простой, использовать TStringList
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
var
  SL : TStringList ;
begin
  SL := TSTringList.Create ;
  SL.Delimiter := ' ' ;
  S:.DelimitedText := 'Paramname 1.691 1.764 1.829 2.007* 1.916' ;
.....
end;



фсё
...
Рейтинг: 0 / 0
28.09.2018, 22:13
    #39710148
Котовасия
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
defecator,

это да. Но ТС хочет иного.
...
Рейтинг: 0 / 0
28.09.2018, 22:20
    #39710150
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Котовасияdefecator,

это да. Но ТС хочет иного.
не увидел иного
...
Рейтинг: 0 / 0
28.09.2018, 22:30
    #39710151
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Код: pascal
1.
  Arr := str.Split([' ', #9]);




Гирлионайльдо
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils, Variants;

function ParseArgs(const str: string): TArray<Variant>;
var
  i, valueInteger: Integer;
  Arr: TArray<string>;
  Value: string;
  valueExtended: Extended;
  delm: char;
begin
  delm := FormatSettings.DecimalSeparator;
  FormatSettings.DecimalSeparator := '.';

  Arr := str.Split([' ']);
  SetLength(Result, Length(Arr));
  for i := Low(Arr) to High(Arr) do
  begin
    Value := Arr[i];
    if TryStrToInt(Value, valueInteger) then
      Result[i] := valueInteger
    else if TryStrToFloat(Value, valueExtended, FormatSettings) then
      Result[i] := valueExtended
    else
      Result[i] := Value;
  end;
  FormatSettings.DecimalSeparator := delm;
end;

var
  v: TArray<Variant>;
  i: Integer;

begin
  try
    v := ParseArgs('Paramname 5 1.691 1.764 1.829 2.007* 1.916');
    for i := Low(v) to High(v) do
    begin
      Writeln(VarToStr(v[i]), ' : ', VarTypeAsText(VarType(v[i])));
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Код: sql
1.
2.
3.
4.
5.
6.
7.
Paramname : UnicodeString
5 : Integer
1,691 : Double
1,764 : Double
1,829 : Double
2.007* : UnicodeString
1,916 : Double

...
Рейтинг: 0 / 0
28.09.2018, 22:33
    #39710153
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Ну или так
Код: pascal
1.
Arr := str.Split(['  ', ' ']);
...
Рейтинг: 0 / 0
01.10.2018, 17:20
    #39711101
Martin114
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
defecator,

Мне уже посоветовали этот вариант. Я сделал так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
function StrCondition(aStr: String): String;
begin
    result := StringReplace(aStr, #32, ';', [rfReplaceAll]); //Заменяем пробелы на ;
    result := StringReplace(result, #9, ';', [rfReplaceAll]); //Заменяем табуляторы на ;
end;
 
procedure GetParameters(const readStr: String);
var
    L: TStringList;
    DelimStr: string;
    i: Integer;
    S: array [0 .. 5] of string;
begin
   L := TStringList.Create; //Создаем СтрингЛист
   L.Delimiter := ';'; //Задаем разделитель
   DelimStr := StrCondition(readStr); //Разбиваем строку на части по разделителю
   L.DelimitedText := DelimStr;
 
   S[0] := L.Strings[0];
   S[1] := L.Strings[1];
   S[2] := L.Strings[2];
   S[3] := L.Strings[3];
 
   L.Free;
end;



Задаем readStr = 'Cmax -0.033 0.021 0.084 0.189 0.204*'. В результате получилось:
DelimStr = 'Cmax;;;;;;-0.033;;;;0.021;;;;0.084;;;;0.189;;;;0.204*'
S[0] = 'Cmax'; S[1] - S[3] - пустые строки. Почему так?
...
Рейтинг: 0 / 0
02.10.2018, 14:53
    #39711723
Martin114
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Получение из строки имени и значений параметров
Проблема решена:

Код: pascal
1.
2.
3.
4.
5.
var L: TStringList;
begin
  L := TStringList.Create;
  L.DelimitedText := StringReplace(readStr, #9, #32, [rfReplaceAll]);
end;
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение из строки имени и значений параметров / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]