2009-04-25 17 views
8

Esiste una funzione Delphi incorporata che converta una stringa come "3.232.00" in virgola mobile? StrToFloat solleva un'eccezione a causa della virgola. O è l'unico modo per rimuovere prima la virgola e poi fare StrToFloat?Converti una stringa con virgole per fluttuare

Grazie.

+3

Esiste un requisito per questo a lavorare in luoghi in cui la virgola viene utilizzato come un punto decimale? Ovunque in Europa, per esempio? –

risposta

15

Lo sai esattamente, quello "." è il separatore decimale e ',' è il separatore di migliaia (sempre)? Se è così, allora dovresti riempire il record TFormatSettings e passarlo a StrToFloat.

FillChar(FS, SizeOf(FS), 0); 
... // filling other fields 
FS.ThousandSeparator := ','; 
FS.DecimalSeparator := '.'; 
V := StrToFloat(S, FS); 
+2

Supponendo che tu sia su Delphi 7 o successivo, altrimenti l'argomento formatetting non è disponibile e StrToFloat ignora felicemente qualsiasi migliaia di elementi che hai impostato. –

+0

È 'FillChar (FS, SizeOf (FS), 0);' veramente necessario? Sembra funzionare anche senza (Delphi XE2). – user1580348

+0

@ user1580348 Sì, è necessario. Può funzionare, ma solo da coincidenze, ovvero: si riempiono tutti i campi (e non vengono aggiunti nuovi campi nella prossima versione di Delphi), oppure una spazzatura che è in FS non viene utilizzata da StrToFloat. ntrol su Delphi RTL: è necessario azzerare i campi non utilizzati. – Alex

4

Prova: StrToFloat(StringReplace('3,232.00', ',', '') È necessario sbarazzarsi delle virgole prima di eseguire la conversione.

In C#/VB.NET io uso sarebbe usare qualcosa di simile decimal.convert("3,232.00", ",", "");

Non conosco nessun modo di fare la conversione senza escludendo i caratteri extra. In effetti, ho una funzione speciale nella mia libreria che rimuove le virgole e i simboli di valuta. Quindi una chiamata in realtà MyConverer.decimalConverter("$3,232.00");

+0

Che non viene compilato. StringReplace ha un 4 ° parametro; 'Flags' – awmross

+1

Basta inserire [] nel parametro flags: StrToFloat (StringReplace ('3.232.00', ',', '', []) –

8

di seguito è ciò che uso. potrebbero esserci modi più efficienti, ma questo funziona per me. in breve, no, non so di alcuna funzione Delphi built-in che converte una stringa flottante contenente le virgole per un galleggiante

{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    safeFloat 

    Strips many bad characters from a string and returns it as a double. 
} 
function safeFloat(sStringFloat : AnsiString) : double; 
var 
    dReturn : double; 

begin 
    sStringFloat := stringReplace(sStringFloat, '%', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, '$', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, ' ', '', [rfIgnoreCase, rfReplaceAll]); 
    sStringFloat := stringReplace(sStringFloat, ',', '', [rfIgnoreCase, rfReplaceAll]); 
    try 
    dReturn := strToFloat(sStringFloat); 
    except 
    dReturn := 0; 
    end; 
    result := dReturn; 

end; 
+4

Per fare in modo che funzioni anche in altre versioni locali: Sostituisci ',' nell'ultima stringa. con ThousandSeparator – mghie

+0

Puoi anche sostituire il simbolo del dollaro con CurrencyString per altre impostazioni locali http://tinyurl.com/cwvu37 – stukelly

0

Ho avuto lo stesso problema quando i miei utenti devono inserire 'scientifica' valori come "1,234.06mV". Qui c'è una virgola, un moltiplicatore (m = x0.001) e un'unità (V). Ho creato una routine di conversione del formato "wide" per gestire questi situtations. Brian

4
function StrToFloat_Universal(pText : string): Extended; 
const 
    EUROPEAN_ST = ','; 
    AMERICAN_ST = '.'; 
var 
    lformatSettings : TFormatSettings; 
    lFinalValue  : string; 
    lAmStDecimalPos : integer; 
    lIndx   : Byte; 
    lIsAmerican  : Boolean; 
    lIsEuropean  : Boolean; 

begin 
    lIsAmerican := False; 
    lIsEuropean := False; 
    for lIndx := Length(pText) - 1 downto 0 do 
    begin 
    if (pText[ lIndx ] = AMERICAN_ST) then 
    begin 
     lIsAmerican := True; 
     pText := StringReplace(pText, ',', '', [ rfIgnoreCase, rfReplaceAll ]); //get rid of thousand incidental separators 
     Break; 
    end; 
    if (pText[ lIndx ] = EUROPEAN_ST) then 
    begin 
     lIsEuropean := True; 
     pText := StringReplace(pText, '.', '', [ rfIgnoreCase, rfReplaceAll ]); //get rid of thousand incidental separators 
     Break; 
    end; 
    end; 
    GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, lformatSettings); 
    if (lformatSettings.DecimalSeparator = EUROPEAN_ST) then 
    begin 
    if lIsAmerican then 
    begin 
     lFinalValue := StringReplace(pText, '.', ',', [ rfIgnoreCase, rfReplaceAll ]); 
    end; 
    end; 
    if (lformatSettings.DecimalSeparator = AMERICAN_ST) then 
    begin 
    if lIsEuropean then 
    begin 
     lFinalValue := StringReplace(pText, ',', '.', [ rfIgnoreCase, rfReplaceAll ]); 
    end; 
    end; 
    pText := lFinalValue; 
    Result := StrToFloat(pText, lformatSettings); 
end; 
1

Io uso una funzione che è in grado di gestire il '' e '' come decimalSeparator ...:

function ConvertToFloat(aNr: String; aDefault:Integer): Extended; 
var 
    sNr, s3R, sWhole, sCent:String; 
    eRC:Extended; 
begin 
    sNr:=ReplaceStr(sNr, ' ', ''); 

    if (Pos('.', sNr) > 0) or (Pos(',', sNr) > 0) then 
    begin 
    // Get 3rd character from right 
    s3R:=LeftStr(RightStr(sNr, 3), 1); 
    if s3R <> DecimalSeparator then 
    begin 
     if not IsNumber(s3R) then 
     begin 
     s3R := DecimalSeparator; 
     sWhole := LeftSr(sNr, Length(sNr) - 3); 
     sCent := (RightStr(sNr, 2); 
     sNr := sWhole + DecimalSeparator + sCent; 
     end 
     else 
     // there are no decimals... add ',00' 
     sNr:=sNr + DecimalSeparator + '00'; 
    end; 
    // DecimalSeparator is present; get rid of other symbols 
    if (DecimalSeparator = '.') and (Pos(',', sNr) > 0) then sNr:=ReplaceStr(sNr, ',', ''); 
    if (DecimalSeparator = ',') and (Pos('.', sNr) > 0) then sNr:=ReplaceStr(sNr, '.', ''); 
    end; 

    eRc := StrToFloat(sNr); 
end; 
0

Myfunction:

function StrIsFloat2 (S: string; out Res: Extended): Boolean; 
var 
    I, PosDecimal: Integer; 
    Ch: Char; 
    STrunc: string; 
    liDots, liComma, J: Byte; 
begin 
    Result := False; 
    if S = '' 
    then Exit; 
    liDots := 0; 
    liComma := 0; 
    for I := 1 to Length(S) do begin 
    Ch := S[I]; 
    if Ch = FormatSettings.DecimalSeparator then begin 
     Inc (liDots); 
     if liDots > 1 then begin 
     Exit; 
     end; 
    end 
    else if (Ch = '-') and (I > 1) then begin 
     Exit; 
    end 
    else if Ch = FormatSettings.ThousandSeparator then begin 
     Inc (liComma); 
    end 
    else if not CharIsCipher(Ch) then begin 
     Exit; 
    end; 
    end; 
    if liComma > 0 then begin 
    PosDecimal := Pos (FormatSettings.DecimalSeparator, S); 
    if PosDecimal = 0 then 
     STrunc := S 
    else 
     STrunc := Copy (S, 1, PosDecimal-1); 
    if STrunc[1] = '-' then 
     Delete (S, 1, 1); 
    if Length(STrunc) < ((liComma * 3) + 2) then 
     Exit; 
    J := 0; 
    for I := Length(STrunc) downto 1 do begin 
     Inc(J); 
     if J mod 4 = 0 then 
     if STrunc[I] <> FormatSettings.ThousandSeparator then 
      Exit; 
    end; 
    S := ReplaceStr (S, FormatSettings.ThousandSeparator, ''); 
    end; 
    try 
    Res := StrToFloat (S); 
    Result := True; 
    except 
    Result := False; 
    end; 
end; 
Problemi correlati