powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение из строки имени и значений параметров
10 сообщений из 10, страница 1 из 1
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #39710148
Котовасия
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
defecator,

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

это да. Но ТС хочет иного.
не увидел иного
...
Рейтинг: 0 / 0
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #39710153
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну или так
Код: pascal
1.
Arr := str.Split(['  ', ' ']);
...
Рейтинг: 0 / 0
Получение из строки имени и значений параметров
    #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
Получение из строки имени и значений параметров
    #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
10 сообщений из 10, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получение из строки имени и значений параметров
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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