我需要從一個字符串中提取數字並將它們放入一個列表中,但是對此有一些規則,例如標識提取的數字是整數還是浮點數。是否有一種簡單的方法從一個字符串中提取數字,遵循特定的規則?
這個任務聽起來很簡單,但隨着時間的推移,我發現自己越來越困惑,並且可以真正做到一些指導。
採取以下測試字符串作爲一個例子:
There are test values: P7 45.826.53.91.7, .5, 66.. 4 and 5.40.3.
的規則解析所述字符串時遵循如下:
號碼不能用字母來preceeded。
如果它找到一個數字並且是而不是後跟一個小數點,那麼該數字就是一個整數。
如果它發現了一些和是後跟一個小數點然後數爲浮點數,例如5.
〜如果更多的數字跟隨在小數點然後數目仍然是一個浮動,例如5.40
〜甲進一步發現小數點應該然後分手的數量,例如5.40.3變爲(5.40浮點型)和(3浮動)
在例如一個字母的以下小數點的情況下,例如
3.H
然後仍添加3.
作爲浮動到列表中(即使在技術上它是無效的)
實施例1
爲了使這一點更爲清晰,同時所需的輸出上面引述的測試字符串應該如下:
從上圖中,淺藍色表示浮點數,淡紅色表示單個整數(但也要注意浮點如何連接在一起被拆分爲單獨的浮點數)。
- 45.826(浮點型)
- 53.91(浮點型)
- 7(整數)
- 5(整數)
- 66。 (浮點型)
- 4(整數)
- 5.40(浮點型)
- 3。(浮點型)
注有66之間故意空格。和3。以上是由於數字格式化的方式。
實施例2:
Anoth3r Te5.t串0.4 ABC 8.1Q 123.45.67.8.9
- 4(整數)
- 8.1(浮動)
- 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.
它顯然沒有得到期望的輸出(失敗碼已被評論),我的做法可能是錯誤的,但我覺得我只需要在這裏和那裏做一些改變,以獲得一個可行的解決方案。
在這一點上,我發現自己很迷茫,儘管認爲答案非常接近,但相當迷茫,任務變得越來越令人憤怒,我非常感謝一些幫助。
編輯1
在這裏,我得到了,因爲不再重複號碼靠近一點點,但結果仍然是明顯的錯誤。
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 }
// Prepare to pull hair out!
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 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: 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.
我的問題是我怎麼能提取數字從一個字符串,將它們添加到列表,並決定如果數字是整數或浮點數?
左邊淡綠色的列表框(需要的輸出)顯示結果應該是什麼,右邊淡藍色的列表框(實際輸出)顯示了我們實際得到的結果。
請指教謝謝。
注意我重新添加了Delphi標籤,因爲我使用XE7,所以請不要刪除它,儘管這個特殊問題在Lazarus中,我最終的解決方案應該適用於XE7和Lazarus。
看看'System.Masks.MatchesMask'函數。我沒有嘗試,但這可能可以幫助你。 –
@DavidHeffernan考慮到我寫出我認爲是一個有效問題的時間(你真的不知道問題是什麼?),這不是一個公平的假設,並且也展示了我的進步和努力,以最好的我的能力。如果我想要一個人爲我做這一切,那麼我不會付出太多的努力,所以請不要假設我想要一個複製和粘貼的答案,我只需要一些指導來幫助我在路上,你只能從程序員的角度來學習而不是複製和粘貼,所以請不要假設我期望有人爲我完成這項工作。 – Craig
那麼你的問題是什麼。非常具體。 –