Prüfen ob String nur aus Ziffern besteht



  • Der Titel sagts schon: Ich möchte prüfen, ob ein String nur Ziffern enthält. Gibt es in der Standard-Bibliothek oder in der VCL eine entsprechende Routine?

    Ich wüsste schon, wie ich es machen könnte aber wozu wenn es schon etwas gibt?

    Danke!

    Keep smilin'
    vi.p



  • Hallo,

    Du könntest mit einer Schleife über alle Zeichen des Strings gehen und dann mit isdigit test ob das zeichen eine Zahl ist.
    Etwa so:

    bool onlyNumbers(const AnsiString& text)
    {
       for( size_t i=1; i<=text.Length(); ++i)
         if( !isdigit(text[i])) return false;
       return true;
    }
    


  • Siehe AnsiString::ToInt() oder AnsiString::ToIntDef().



  • @Braunstein:

    Dankeschön!

    Exakt so hatte ich es bereits gelöst. Wollte nur wissen, obs was "vorgefertigtes" gibt. Aber so gehts natürlich auch...

    Keep smilin'
    vi.p



  • @Joe_M.

    Meine Zahlen sind dafür leider zu groß. Es gäbe da noch StrToInt64Def. Die Frage ist welche Methode (zeichenweise prüfen vs. konvertieren) effizienter ist.



  • Zeichenweise prüfen dürfte effizienter sein, da hier schon zeitig abgebrochen werden kann.
    Es kann natürlich sein, dass StrToInt etwas ganz ähnliches macht. 🙂



  • Folgender Versuchsaufbau:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	AnsiString asTest = "12345678901234567890";
    	int i;
    	bool Result;
    	int start;
    	int ende;
    	int maxloops = 10000000;
    
    	// StandardLib
    	start = GetTickCount();
    	for (i = 0; i < maxloops; i++)
    		Result = stdIsDigit(asTest);
    	ende = GetTickCount();
    	Memo1->Lines->Add(AnsiString(ende - start));
    
    	// ToIntDef
    	start = GetTickCount();
    	for (i = 0; i < maxloops; i++)
    		Result = tiIsDigit(asTest);
    	ende = GetTickCount();
    	Memo1->Lines->Add(AnsiString(ende - start));
    }
    //---------------------------------------------------------------------------
    
    bool __fastcall TForm1::stdIsDigit(AnsiString x)
    {
    	int max = x.Length();
    	for (int i = 1; i <= max; ++i)
    		if (!isdigit(x[i]))
    			return false;
    	return true;
    }
    
    bool __fastcall TForm1::tiIsDigit(AnsiString x)
    {
    	if (x.ToIntDef(-1) == -1)
    		return false;
    	else
    		return true;
    
    }
    

    führt zu folgender Ausgabe:
    17828
    2484

    Ein klarer Vorteil für ToIntDef...



  • Stimmt, im Prinzip. Hast du auch mal die Ergebnisse verglichen?



  • ToIntDef geht doch gar nicht für so große Zahlen. gibt ja nur int zurück.



  • Ok, zugegeben, die Zahl im String war zu groß. Aber auch wenn man 2147483647 im String einsetzt, ist ToIntDef um den Faktor 4 schneller.



  • Das ist richtig. Die Funktion sollte aber immer richtige Ergebnisse liefern. 😉 Über die Größe der Strings war ja keine Angabe gemacht worden.
    Übrigens, wenn du den String als konstante Referenz statt als Kopie übergibst sparst du nochmal Zeit.



  • Diese Version hier ist etwas schneller als die Vorige

    bool onlyNumbers(const AnsiString& x)
    {
        int max = x.Length();
        const char* cstr(x.c_str());
        for (int i = 0; i < max; ++i)
            if (!isdigit(cstr[i]))
                return false;
        return true;
    }
    


  • Hallo!

    Die Strings die ich zu prüfen habe sind entweder acht- oder zwölfstellig.
    Bei ersteren dürfte es noch halbwegs gehen, letztere sind definitiv zu groß.


Anmelden zum Antworten