这个任务听起来很简单,但随着时间的推移,我越来越感到困惑,可能真的有一些指导。
以下列测试字符串为例:
There are test values: P7 45.826.53.91.7,.5,66.. 4 and 5.40.3.@H_404_7@解析字符串时要遵循的规则如下:
>数字不能超过一封信。
>如果它找到一个数字,后跟一个小数点,那么数字就是一个整数。
>如果它找到一个数字,后跟一个小数点,则该数字是一个浮点数,例如5。
>〜如果更多数字跟随小数点,则数字仍然是浮点数,例如5.40
>〜进一步发现小数点应该分解数字,例如5.40.3变为(5.40 Float)和(3 Float)
>如果以小数点为例,例如3.H,然后仍然将3作为浮点添加到列表中(即使在技术上无效)实施例1
为了使这一点更清楚,将测试字符串引用到所需输出的上方应如下所示:
从上图中,浅蓝色表示浮点数,浅红色表示单个整数(但也要注意浮点连接在一起的情况,分为单独的浮点数)。
请注意,66之间有刻意的空格。和3。以上是由于格式化数字的方式。
示例2:
Anoth3r Te5.t string .4 abc 8.1Q 123.45.67.8.9
为了给出一个更好的想法,我创建了一个新的项目,同时测试如下:
现在到了实际的任务。我想也许我可以从字符串中读取每个字符,并根据上述规则识别有效的数字,然后将它们列入列表。
就我的能力而言,这是我能管理的最好的:
代码如下:
unit Unit1; {$mode objfpc}{$H+} interface uses Classes,SysUtils,FileUtil,Forms,Controls,Graphics,Dialogs,StdCtrls; type TForm1 = class(TForm) btnParseString: TButton; edtTestString: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; lstDesiredOutput: TListBox; lstActualOutput: TListBox; procedure btnParseStringClick(Sender: TObject); private FDone: Boolean; FIdx: Integer; procedure ParseString(const Str: string; var OutValue,OutKind: string); public { public declarations } end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.ParseString(const Str: string; var OutValue,OutKind: string); var CH1,CH2: Char; begin Inc(FIdx); CH1 := Str[FIdx]; case CH1 of '0'..'9': // Found a number begin CH2 := Str[FIdx - 1]; if not (CH2 in ['A'..'Z']) then begin OutKind := 'Integer'; // Try to determine float... //while (CH1 in ['0'..'9','.']) do //begin // case Str[FIdx] of // '.': // begin // CH2 := Str[FIdx + 1]; // if not (CH2 in ['0'..'9']) then // begin // OutKind := 'Float'; // //Inc(FIdx); // end; // end; // end; //end; end; OutValue := Str[FIdx]; end; end; FDone := FIdx = Length(Str); end; procedure TForm1.btnParseStringClick(Sender: TObject); var S,SKind: string; begin lstActualOutput.Items.Clear; FDone := False; FIdx := 0; repeat ParseString(edtTestString.Text,S,SKind); if (S <> '') and (SKind <> '') then begin lstActualOutput.Items.Add(S + ' (' + SKind + ')'); end; until FDone = True; end; end.@H_404_7@它显然没有给出期望的输出(失败的代码已被注释掉),我的方法可能是错误的,但我觉得我只需要在这里和那里做一些工作的解决方案。
在这一点上,我发现自己很困惑,相当失落,尽管答案相当接近,任务变得越来越激烈,我真的很感激一些帮助。
编辑1
在这里我有一个更近的一点,因为不再重复的数字,但结果仍然显然是错误的。
unit Unit1; {$mode objfpc}{$H+} interface uses Classes,OutKind: string); public { public declarations } end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } // Prepare to pull hair out! procedure TForm1.ParseString(const Str: string; var OutValue,CH2: Char; begin Inc(FIdx); CH1 := Str[FIdx]; case CH1 of '0'..'9': // Found the start of a new number begin CH1 := Str[FIdx]; // make sure prevIoUs character is not a letter CH2 := Str[FIdx - 1]; if not (CH2 in ['A'..'Z']) then begin OutKind := 'Integer'; // Try to determine float... //while (CH1 in ['0'..'9','.']) do //begin // OutKind := 'Float'; // case Str[FIdx] of // '.': // begin // CH2 := Str[FIdx + 1]; // if not (CH2 in ['0'..'9']) then // begin // OutKind := 'Float'; // Break; // end; // end; // end; // Inc(FIdx); // CH1 := Str[FIdx]; //end; end; OutValue := Str[FIdx]; end; end; OutValue := Str[FIdx]; FDone := Str[FIdx] = #0; end; procedure TForm1.btnParseStringClick(Sender: TObject); var S,SKind); if (S <> '') and (SKind <> '') then begin lstActualOutput.Items.Add(S + ' (' + SKind + ')'); end; until FDone = True; end; end.@H_404_7@我的问题是如何从字符串中提取数字,将它们添加到列表中,并确定数字是整数还是浮点数?
左边的绿色绿色列表框(所需输出)显示结果应该是什么,右侧的淡蓝色列表框(实际输出)显示了我们实际获得的结果。
请指教谢谢
注意我重新添加了Delphi标签,因为我使用XE7,所以请不要删除它,虽然这个特别的问题是在拉撒路我的最终解决方案应该适用于XE7和拉撒路。
解决方法
每个字符都会导致状态之间的转换。
例如,当你处于状态“integer start”并且满足空格时,你会得到整数值,而FSM进入“任何需要的”状态。
如果处于状态“整数开始”并且满足’。’,则FSM进入状态“float或整数列表开始”等等。