Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 比如StrTok()或Sscanf()?_Delphi_Modbus - Fatal编程技术网

Delphi 比如StrTok()或Sscanf()?

Delphi 比如StrTok()或Sscanf()?,delphi,modbus,Delphi,Modbus,因此,我通过串行端口从ModBos读取数据,得到如下读数:'+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003' 基本上,将始终有8个浮点读数,前面有加号或减号,尽管它们可能具有不同的字符长度 从float数组(或string数组或TSringList)中获取值的最有效方法是什么 我不确定,但这可能是时间关键,因此效率可能远远超过优雅。您可以下载并使用移植到Delphi的VC++。我会这样做: type TFloatArray =

因此,我通过串行端口从ModBos读取数据,得到如下读数:
'+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003'

基本上,将始终有8个浮点读数,前面有加号或减号,尽管它们可能具有不同的字符长度

从float数组(或string数组或TSringList)中获取值的最有效方法是什么


我不确定,但这可能是时间关键,因此效率可能远远超过优雅。

您可以下载并使用移植到Delphi的VC++。

我会这样做:

type
  TFloatArray = array[0..7] of Double;

procedure ParseFloats(const aFloatStr: string;
  var aFloatArray: TFloatArray);
var
  lPos: Integer;
  lNextPos: Integer;
  lPosPositive: Integer;
  lPosNegative: Integer;
  i: Integer;
  lFormatSettings: TFormatSettings;
begin
  //do not forget formatsettings, or you will get problems with regional settings
  lFormatSettings.DecimalSeparator := '.';
  lFormatSettings.ThousandSeparator := ',';
  lPos := 1;
  for i := 0 to High(aFloatArray) do
  begin
    lPosPositive := PosEx('+', aFloatStr, lPos + 1);
    lPosNegative := PosEx('-', aFloatStr, lPos + 1);
    if lPosPositive = 0 then
      lNextPos := lPosNegative
    else if lPosNegative = 0 then
      lNextPos := lPosPositive
    else
      lNextPos := Min(lPosPositive, lPosNegative);
    if lNextPos = 0 then
      lNextPos := Length(aFloatStr) + 1;
    aFloatArray[i] := StrToFloat(Copy(aFloatStr, lPos, lNextPos - lPos), lFormatSettings);
    lPos := lNextPos;
  end;
end;

//call like this
var
  lFloats: TFloatArray;
begin
  ParseFloats('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003', lFloats);
end;
因为总是有8个浮点值,一个8倍的固定数组就足够了。我将字符串操作限制在最低限度,每个浮点值只复制一次字符串。重要的是TFormatSetting,否则在十进制分隔符不是点的系统(如我的系统)上会出现错误

这里没有异常处理,我希望字符串包含8个浮点值,不多不少。

您可以使用该类来解析字符串

检查此示例应用程序

program ParserDemo;

{$APPTYPE CONSOLE}

uses
  Classes,
  SysUtils;

procedure ProcessModBosOutPut(OutPut : string);
var
 StringStream  : TStringStream;
 Parser        : TParser;
 dValue        : Double;
 sValue        : string;
 FormatSettings: TFormatSettings;
begin
   FormatSettings.DecimalSeparator :='.';
   FormatSettings.ThousandSeparator:=',';
   //transform the output string to fit with the TParser logic
   OutPut:=StringReplace(OutPut,'+',' ',[rfReplaceAll]); //replace  '+' sign with a space
   OutPut:=StringReplace(OutPut,'-',' -',[rfReplaceAll]); //insert a empty space after of a '-' sign

   StringStream:=TStringStream.Create(OutPut);
   Parser:=TParser.Create(StringStream);
   try
        while Parser.Token <> toEOF do
        begin
           sValue:=Parser.TokenString; //get the string 
           dValue:=StrToFloat(sValue,FormatSettings); //convert the string
           //do something with the float value
           Writeln(FloatToStr(dValue));
           Parser.NextToken;
        end;
   finally
     Parser.Free;
     StringStream.Free;
   end;
end;

begin
  try
    ProcessModBosOutPut('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
  Readln;
end.
programmparserdemo;
{$APPTYPE控制台}
使用
班级,
SysUtils;
过程ProcessModBosOutPut(输出:字符串);
变量
StringStream:TStringStream;
解析器:TParser;
d值:双倍;
sValue:字符串;
格式设置:t格式设置;
开始
FormatSettings.DecimalSeparator:='.';
FormatSettings.MilliandSeparator:=',';
//转换输出字符串以适应TParser逻辑
输出:=StringReplace(输出“+”,“[rfReplaceAll])//将“+”符号替换为空格
输出:=StringReplace(输出'-','-',[rfReplaceAll])//在“-”号后面插入空格
StringStream:=TStringStream.Create(输出);
解析器:=TParser.Create(StringStream);
尝试
while Parser.toedo的标记
开始
sValue:=Parser.TokenString//获取字符串
dValue:=StrToFloat(sValue,FormatSettings)//转换字符串
//用浮点值做些什么
Writeln(FloatToStr(dValue));
Parser.NextToken;
结束;
最后
解析器。免费;
StringStream.免费;
结束;
结束;
开始
尝试
ProcessModBos输出('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
除了
关于E:Exception-do
Writeln(E.Classname,“:”,E.Message);
结束;
Readln;
结束。

对于那些有兴趣重复性能测试的人,可以使用Delphi XE将以下内容复制并粘贴到新的控制台项目中

program Project1;

uses
  classes,
  sysutils,
  strutils,
  math;

{$APPTYPE CONSOLE}

type
  TFloatArray = array[0..7] of Double;

procedure ParseFloats_TheFox(const aFloatStr: string;
  var aFloatArray: TFloatArray);
var
  lPos: Integer;
  lNextPos: Integer;
  lPosPositive: Integer;
  lPosNegative: Integer;
  i: Integer;
  lFormatSettings: TFormatSettings;
begin
  //do not forget formatsettings, or you will get problems with regional settings
  lFormatSettings.DecimalSeparator := '.';
  lFormatSettings.ThousandSeparator := ',';
  lPos := 1;
  for i := 0 to High(aFloatArray) do
  begin
    lPosPositive := PosEx('+', aFloatStr, lPos + 1);
    lPosNegative := PosEx('-', aFloatStr, lPos + 1);
    if lPosPositive = 0 then
      lNextPos := lPosNegative
    else if lPosNegative = 0 then
      lNextPos := lPosPositive
    else
      lNextPos := Min(lPosPositive, lPosNegative);
    if lNextPos = 0 then
      lNextPos := Length(aFloatStr) + 1;
    //aFloatArray[i] := StrToFloat(Copy(aFloatStr, lPos, lNextPos - lPos), lFormatSettings);
    WriteLn(StrToFloat(Copy(aFloatStr, lPos, lNextPos - lPos), lFormatSettings));
    lPos := lNextPos;
  end;
end;

procedure ProcessModBosOutPut_RRUZ(OutPut : string);
var
 StringStream  : TStringStream;
 Parser        : TParser;
 dValue        : Double;
 sValue        : string;
 FormatSettings: TFormatSettings;
begin
   FormatSettings.DecimalSeparator :='.';
   FormatSettings.ThousandSeparator:=',';
   //transform the output string to fit with the TParser logic
   OutPut:=StringReplace(OutPut,'+',' ',[rfReplaceAll]); //replace  '+' sign with a space
   OutPut:=StringReplace(OutPut,'-',' -',[rfReplaceAll]); //insert a empty space after of a '-' sign

   StringStream:=TStringStream.Create(OutPut);
   Parser:=TParser.Create(StringStream);
   try
        while Parser.Token <> toEOF do
        begin
           sValue:=Parser.TokenString; //get the string
           dValue:=StrToFloat(sValue,FormatSettings); //convert the string
           //do something with the float value
           Writeln(FloatToStr(dValue));
           Parser.NextToken;
        end;
   finally
     Parser.Free;
     StringStream.Free;
   end;
end;


procedure Jorn(const floatstring: string);
var
  i,idx: Integer;
  tmpArray: Array[0..7] of Double;
  tmpString: ShortString;
begin
  DecimalSeparator := '.';

  idx := Low(tmpArray);
  tmpString := '';

  tmpString := floatstring[1];
  for i := 2 to Length(floatstring) do
  begin
    if floatstring[i] in ['+', '-']
    then begin
      writeln(strtofloat(tmpString));
      //TryStrToFloat(tmpString, tmpArray[idx]);
      Inc(idx);
      tmpString := floatstring[i];
    end
    else begin
      tmpString := tmpString + floatstring[i];
    end;
  end;
  //TryStrToFloat(tmpString, tmpArray[idx]);
  writeln(strtofloat(tmpString));
end;

//call like this
var
  lFloats: TFloatArray;
  I: Integer;
begin
  for I := 0 to 999 do
  begin
    ParseFloats_TheFox      ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003', lFloats);
    WriteLn('The Fox');

    ProcessModBosOutPut_RRUZ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
    WriteLn('RRUZ');

    Jorn                    ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
    WriteLn('Jorn');
  end;

  readln;
end.
程序项目1;
使用
班级,
sysutils,
支柱,
数学;
{$APPTYPE控制台}
类型
TFloatArray=双精度数组[0..7];
过程解析浮点数(const aflautstr:string;
var AFLOATARY:TFLOATARY);
变量
lPos:整数;
lNextPos:整数;
lPosPositive:整数;
lPosNegative:整数;
i:整数;
l格式设置:t格式设置;
开始
//不要忘记格式设置,否则您将在区域设置中遇到问题
lFormatSettings.DecimalSeparator:='.';
lFormatSettings.ThousandSeparator:=',';
LPO:=1;
对于i:=0到高(漂浮数组)do
开始
lPosPositive:=PosEx(+',aFloatStr,lPos+1);
lPos阴性:=PosEx('-',aFloatStr,lPos+1);
如果lPosPositive=0,则
lNextPos:=lPosNegative
否则,如果lPosNegative=0,则
lNextPos:=LpoPositive
其他的
lNextPos:=Min(lPosPositive,lPosNegative);
如果lNextPos=0,则
lNextPos:=长度(漂浮长度)+1;
//aFloatArray[i]:=StrToFloat(复制(aFloatStr,lPos,lNextPos-lPos),lFormatSettings);
WriteLn(StrToFloat(拷贝(aFloatStr、lPos、lNextPos-lPos)、lFormatSettings));
lPos:=lNextPos;
结束;
结束;
过程进程modbosoutput_RRUZ(输出:字符串);
变量
StringStream:TStringStream;
解析器:TParser;
d值:双倍;
sValue:字符串;
格式设置:t格式设置;
开始
FormatSettings.DecimalSeparator:='.';
FormatSettings.MilliandSeparator:=',';
//转换输出字符串以适应TParser逻辑
输出:=StringReplace(输出“+”,“[rfReplaceAll])//将“+”符号替换为空格
输出:=StringReplace(输出'-','-',[rfReplaceAll])//在“-”号后面插入空格
StringStream:=TStringStream.Create(输出);
解析器:=TParser.Create(StringStream);
尝试
while Parser.toedo的标记
开始
sValue:=Parser.TokenString//获取字符串
dValue:=StrToFloat(sValue,FormatSettings)//转换字符串
//用浮点值做些什么
Writeln(FloatToStr(dValue));
Parser.NextToken;
结束;
最后
解析器。免费;
StringStream.免费;
结束;
结束;
过程Jorn(常量floatstring:string);
变量
i、 idx:整数;
tmpArray:Double的数组[0..7];
tmpString:短字符串;
开始
小数分隔符:='';
idx:=低(tmpArray);
tmpString:='';
tmpString:=floatstring[1];
对于i:=2到长度(floatstring)do
开始
如果浮动字符串[i]位于['+','-']
然后开始
writeln(strtofloat(tmpString));
//trystrtofolat(tmpString,tmpArray[idx]);
公司(idx),;
tmpString:=floatstring[i];
结束
否则开始
tmpString:=tmpString+floatstring[i];
结束;
结束;
//trystrtofolat(tmpString,tmpArray[idx]);
writeln(strtofloat(tmpString));
结束;
//像这样打电话
变量
lFloats:TFloatArray;
I:整数;
开始
对于I:=0到999 do
开始
解析浮箱('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003',lFloats);
WriteLn(“狐狸”);
ProcessModBos输出_RRUZ(“+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003”);
书面形式(“RRUZ”);
乔恩(“+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003”);
书面形式(“Jorn”);
结束;
readln;
结束。

如果您想调用sscanf,我只需调用msvcrt.dll中的一个,它是一个官方的Windows系统
program Project1;

uses
  classes,
  sysutils,
  strutils,
  math;

{$APPTYPE CONSOLE}

type
  TFloatArray = array[0..7] of Double;

procedure ParseFloats_TheFox(const aFloatStr: string;
  var aFloatArray: TFloatArray);
var
  lPos: Integer;
  lNextPos: Integer;
  lPosPositive: Integer;
  lPosNegative: Integer;
  i: Integer;
  lFormatSettings: TFormatSettings;
begin
  //do not forget formatsettings, or you will get problems with regional settings
  lFormatSettings.DecimalSeparator := '.';
  lFormatSettings.ThousandSeparator := ',';
  lPos := 1;
  for i := 0 to High(aFloatArray) do
  begin
    lPosPositive := PosEx('+', aFloatStr, lPos + 1);
    lPosNegative := PosEx('-', aFloatStr, lPos + 1);
    if lPosPositive = 0 then
      lNextPos := lPosNegative
    else if lPosNegative = 0 then
      lNextPos := lPosPositive
    else
      lNextPos := Min(lPosPositive, lPosNegative);
    if lNextPos = 0 then
      lNextPos := Length(aFloatStr) + 1;
    //aFloatArray[i] := StrToFloat(Copy(aFloatStr, lPos, lNextPos - lPos), lFormatSettings);
    WriteLn(StrToFloat(Copy(aFloatStr, lPos, lNextPos - lPos), lFormatSettings));
    lPos := lNextPos;
  end;
end;

procedure ProcessModBosOutPut_RRUZ(OutPut : string);
var
 StringStream  : TStringStream;
 Parser        : TParser;
 dValue        : Double;
 sValue        : string;
 FormatSettings: TFormatSettings;
begin
   FormatSettings.DecimalSeparator :='.';
   FormatSettings.ThousandSeparator:=',';
   //transform the output string to fit with the TParser logic
   OutPut:=StringReplace(OutPut,'+',' ',[rfReplaceAll]); //replace  '+' sign with a space
   OutPut:=StringReplace(OutPut,'-',' -',[rfReplaceAll]); //insert a empty space after of a '-' sign

   StringStream:=TStringStream.Create(OutPut);
   Parser:=TParser.Create(StringStream);
   try
        while Parser.Token <> toEOF do
        begin
           sValue:=Parser.TokenString; //get the string
           dValue:=StrToFloat(sValue,FormatSettings); //convert the string
           //do something with the float value
           Writeln(FloatToStr(dValue));
           Parser.NextToken;
        end;
   finally
     Parser.Free;
     StringStream.Free;
   end;
end;


procedure Jorn(const floatstring: string);
var
  i,idx: Integer;
  tmpArray: Array[0..7] of Double;
  tmpString: ShortString;
begin
  DecimalSeparator := '.';

  idx := Low(tmpArray);
  tmpString := '';

  tmpString := floatstring[1];
  for i := 2 to Length(floatstring) do
  begin
    if floatstring[i] in ['+', '-']
    then begin
      writeln(strtofloat(tmpString));
      //TryStrToFloat(tmpString, tmpArray[idx]);
      Inc(idx);
      tmpString := floatstring[i];
    end
    else begin
      tmpString := tmpString + floatstring[i];
    end;
  end;
  //TryStrToFloat(tmpString, tmpArray[idx]);
  writeln(strtofloat(tmpString));
end;

//call like this
var
  lFloats: TFloatArray;
  I: Integer;
begin
  for I := 0 to 999 do
  begin
    ParseFloats_TheFox      ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003', lFloats);
    WriteLn('The Fox');

    ProcessModBosOutPut_RRUZ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
    WriteLn('RRUZ');

    Jorn                    ('+0020.8+0022.8-00.046-00.002-00.005-001.99+00.000+00.003');
    WriteLn('Jorn');
  end;

  readln;
end.