String auf Ziffern prüfen



  • Hallo zusammen,
    ich habe folgende Frage/Problem.

    for (int i = 1; i == text.length(); i++ ) {
    if( text[i] == '0' || text[i] == '1' || text[i] == '2' || text[i] == '3'|| text[i] == '4' || text[i] == '5' || text[i] == '6' || text[i] == '7' || text[i] == '8' || text[i] == '9') {
    std::cout << "success2" << std::endl;

    }
    

    Ich möchte ein String auf Ziffern prüfen. Wieso funktioniert das so nicht? kann mir jemand weiterhelfen?
    Vielen Dank!



  • https://www.c-plusplus.net/forum/topic/200753/du-brauchst-hilfe

    Minimal vollständiges Beispiel, und packe deinen Code bitte in

    ```
    mein code
    ```


  • @Johnny01 „funktioniert nicht“ ist keine Fehlerbeschreibung.

    Schau dir noch einmal an, wie eine for-Schleife arbeitet.

    Indexe fangen in C++ in der Regel bei 0 an.



  • @Johnny01 sagte in String auf Ziffern prüfen:

    i == text.length()

    Ist auch Quatsch



  • @Johnny01 sagte in String auf Ziffern prüfen:

    for (int i = 1; i == text.length(); i++ ) {

    Verwende immer dann, wenn du über alles loopen willst, eine range-for-Loop.

    Also for (char ch : text) { ... }

    Wenn du mit Index arbeiten willst (wie gesagt, du solltest die Range-Variante oben bevorzugen), dann lautet der Standardfall:
    for (size_t i = 0; i < std::size(container_variable); ++i) { ... } - merke: bei 0 anfangen und der Vergleich muss "solange der Index echt kleiner als die Länge ist" lauten. Ab C++17 gibt es std::size, davor nimmst du die Memberfunktion size(). (bei Strings alternativ length() - aber da bei sowas wie vector nur size() geht, würde ich auch bei Strings size() nehmen)

    if( text[i] == '0' || text[i] == '1' || text[i] == '2' || text[i] == '3'|| text[i] == '4' || text[i] == '5' || text[i] == '6' || text[i] == '7' || text[i] == '8' || text[i] == '9') {

    Schau dir mal dazu https://en.cppreference.com/w/cpp/string/byte/isdigit an.

    Zusammen also:

    for (char ch : text) {
        if (std::isdigit(ch) {
            std::cout << "Zeichen " << ch << " ist eine Ziffer.\n";
        } else {
            std::cout << "Zeichen " << ch << " ist KEINE Ziffer.\n";
        }
    }
    


  • @wob Vorsicht, verwende isdigit nie mit char. Das geht ins Auge, wenn char signed und der Wert negativ ist.

    if (std::isdigit(static_cast<unsigned char>(ch)) {
    


  • @manni66 sagte in String auf Ziffern prüfen:

    @wob Vorsicht, verwende isdigit nie mit char. Das geht ins Auge, wenn char signed und der Wert negativ ist.

    if (std::isdigit(static_cast<unsigned char>(ch)) {
    

    oops, danke. Könnte sein, dass ich das häufiger falsch gemacht habe, und weil auf meinem System char == unsigned char ist, ist das nie aufgefallen. (und in meinem Code oben fehlt auch noch eine runde schließende Klammer).



  • @wob sagte in String auf Ziffern prüfen:

    @manni66 sagte in String auf Ziffern prüfen:

    @wob Vorsicht, verwende isdigit nie mit char. Das geht ins Auge, wenn char signed und der Wert negativ ist.

    if (std::isdigit(static_cast<unsigned char>(ch)) {
    

    oops, danke. Könnte sein, dass ich das häufiger falsch gemacht habe

    Ja, die berühmt-berüchtigten C++-Altlasten. Solche Funktionen würde man heute jedem Anfänger um die Ohren hauen, wenn er sowas abliefern würde 😉 . Gibt es bei diesen steinalten Char-Funktionen tief in der C-Standardbibliothek eigentlich irgendwo auch etwas, was diesen int-Parameter rechtfertigt? Irgend ein altertümliches Fehler-Handling, wo negative Zahlen Fehlercodes sind oder sowas? Im '<cctype>'-Header seh ich auf en ersten Blick nichts dergleichen.


  • Mod

    @Finnegan sagte in String auf Ziffern prüfen:

    Gibt es bei diesen steinalten Char-Funktionen tief in der C-Standardbibliothek eigentlich irgendwo auch etwas, was diesen int-Parameter rechtfertigt? Irgend ein altertümliches Fehler-Handling, wo negative Zahlen Fehlercodes sind oder sowas? Im '<cctype>'-Header seh ich auf en ersten Blick nichts dergleichen.

    Soll das nicht EOF als Parameter ermöglichen?


  • Mod

    @Finnegan sagte in String auf Ziffern prüfen:

    Ja, die berühmt-berüchtigten C++-Altlasten. Solche Funktionen würde man heute jedem Anfänger um die Ohren hauen, wenn er sowas abliefern würde 😉 . Gibt es bei diesen steinalten Char-Funktionen tief in der C-Standardbibliothek eigentlich irgendwo auch etwas, was diesen int-Parameter rechtfertigt? Irgend ein altertümliches Fehler-Handling, wo negative Zahlen Fehlercodes sind oder sowas? Im '<cctype>'-Header seh ich auf en ersten Blick nichts dergleichen.

    Es geht um die EOF-Signalisierung, geerbt von C, und nie benutzt seit es Streams (mit Eof-Flag) gibt. Aber in C wird damit im Rückgabewert von Zeichenlesefunktionen signalisiert, dass ein Lesefehler aufgetreten ist. Und das ist meistens so etwas wie -1 um Konflikte mit regulären Zeichen zu vermeiden. Die Anleitung von isdigit sagt ja auch explizit, dass das Verhalten trotz negativer Werte nicht undefiniert ist, falls das Zeichen gleich dem EOF-Sonderwert ist.



  • Danke. Und Btw. witzig, was für Diskussionen hier immer wieder durch unschuldige Anfängerfragen losgetreten werden. Da weiss @Johnny01 gleich auf was er sich in Zununft alles gefasst machen muss, wenn er sich auf eine Sprache wie C++ einlässt 👍 ... da kann hinterher niemand sagen, er hätte nicht gewusst, was da auf einen zurollt 😉


  • Mod

    @Finnegan sagte in String auf Ziffern prüfen:

    Danke. Und Btw. witzig, was für Diskussionen hier immer wieder durch unschuldige Anfängerfragen losgetreten werden. Da weiss @Johnny01 gleich auf was er sich in Zununft alles gefasst machen muss, wenn er sich auf eine Sprache wie C++ einlässt 👍 ... da kann hinterher niemand sagen, er hätte nicht gewusst, was da auf einen zurollt 😉

    Sehr wahrscheinlich braucht er das, was hier gefragt ist, ja nicht wirklich. Das ist entweder eine Übungsaufgabe "prüfen Sie auf Ziffern", die man nie wieder braucht, oder es ist eine Vorstufe dazu, das Rad selber neu erfinden (also, dass das später mal Zahlen parsen soll oder so), was man generell nicht machen sollte. Denn das man isdigit in high-level Anwendungscode braucht dürfte echt selten sein. Und wenn man meint, low-level IO-Bibliotheken selber neu erfinden zu müssen, dann ist dies eines der geringsten Probleme, auf die man stoßen wird.



  • BTW: Der ganze Ärger hätte sich auch vermeiden lassen. Wenn man EOF z.B. mit -129 oder auch einfach -200 festlegt hat man auf 8-Bit char Systemen kein Problem (mit CHAR_BIT != 8 braucht man halt entsprechend andere Werte). Man hätte also ohne weiteres definieren können dass man char, signed char und unsigned char Werte 1:1 da reinschieben kann ohne UB oder ein falsches Ergebnis zu bekommen.


  • Mod

    @hustbaer Es ist der Standard, der festlegt dass die Klassifizierungsfunktionen nur auf unsigned char Range definiert sind. Der Standard hat EOF nicht als -1 festgelegt, u.a. aus dem Grund, den du selber suggerierst, dass die Range von char-Typen nicht festgelegt wird. Du musst schon vorschlagen, wie der Standard, ohne solche Annahmen zu machen, das Problem lösen kann. Der Standard würde ja dadurch, dass er isalnum etc. mit char Range erlaubt, die Implementierung zwingen, EOF so festzulegen wie Du vorschlägst (d.h. -1 wäre nur bedingt zulässig). Dann haben wir plötzlich X verschiedene EOF Werte je nach Compiler/Platform. 🤮

    Edit^2:
    Oder "alle" einigen sich darauf, EOF mit irgendeinem genügend kleinen Wert zu belegen. von CHAR_BIT > 16 habe ich nicht gehört, aber das schliesst nicht aus, dass es das irgendwann geben wird, oder gegeben hat. Der Koordinierungsaufwand ist diese paar Funktionen hier gar nicht wert. Und dann sind die Systeme, auf denen CHAR_BIT == 16 ist, manchmal auch noch sizeof(int) == 1. Dann ist zwar EOF == -1 gültig, weil man char als vorzeichenlos definiert, aber 2161-2^{16}-1 nicht mehr.... Das heisst, das Problem lässt sich nicht einheitlich lösen, wenn es sowohl ein System mit 16 Bit (unsigned) char/int gibt, als auch 16 bit signed char/32 bit int? Or am I missing something?

    KIar haette man auf POSIX deinen Vorschlag berücksichtigen können. Aber -1 ist als universeller Wert keine schlechte Wahl IMHO.
    Edit: Ich glaub nicht, dass die Platform als Annahme reicht. Es wäre einfach unbesonnen, EOF in irgendeiner Weise zu parametrisieren. Der Wert wird in so vielen Ecken verwendet, z.B. in LUTs, dass es deutlich simpler ist, einfach einen universalen Wert zu wählen, anstatt einen platformabhaengigen.



  • Wie würde man denn heute im modernen C++ einzelne Zeichen eines Strings darauf testen ob sie eine Ziffer sind oder nicht?


  • Mod

    @CppConst sagte in String auf Ziffern prüfen:

    Wie würde man denn heute im modernen C++ einzelne Zeichen eines Strings darauf testen ob sie eine Ziffer sind oder nicht?

    Die Frage ist nicht wie, sondern warum. Warum denkst du das in modernem C++ zu brauchen?



  • @CppConst sagte in String auf Ziffern prüfen:

    Wie würde man denn heute im modernen C++ einzelne Zeichen eines Strings darauf testen ob sie eine Ziffer sind oder nicht?

    Das würde man so machen:

    #include <ctre.hpp>
    bool string_of_digits(std::string_view sv) { 
        return ctre::match<"^[0-9]+$">(sv);
    }
    

    An sowas wie if (ch >= '0' && ch <= '9') würde ich heutzutage keine Gedanken mehr verschwenden!


  • Mod

    Regexmatches um eine Simpelabfrage zu ersetzen? Da fehlt noch, dass du einen Container auf einer VM startest, die mit dem String einen Webservice fragt, woraus der String besteht und das ergebnis in einer Blockchain speichert.


  • Mod

    @SeppJ sagte in String auf Ziffern prüfen:

    Regexmatches um eine Simpelabfrage zu ersetzen? Da fehlen noch mindestens 3 Webservices die du fragen musst und irgendwo muss noch eine Blockchain rein.

    Ich vermute stark, dass ctre constexpr ist, und die Konstruktion des DFAs zur Compilezeit geschieht.
    Edit: ja, es ist natuerlich immer noch overengineered, lol. Ich dachte du beziehst Dich auf die Performance



  • @SeppJ sagte in String auf Ziffern prüfen:

    Die Frage ist nicht wie, sondern warum. Warum denkst du das in modernem C++ zu brauchen?

    Weil man die Tests nicht mehr mit C Code machen will? Ich hatte vor etlichen Jahren das Problem, dass ich eine Plattform unabhängige Version (d.h. unabhängig von der locale Einstellungen des OS) dafür brauchte, so hatte ich das mit 8Bit Char (UNIX) geschrieben. Das Programm hat hauptsächlich Texte verarbeitet und in eine DB abgelegt.


Log in to reply