Testen ob ein String binär ist



  • Hallo zusammen,
    ich will testen ob ein String binär ist und möchte hierbei mit Zeigern arbeiten, damit ich mich mit den Zeigern etwas vertraut mache. Allerdings gibt es da ein Problem mit dem else-Befehl. Dieser ist grau hinterlegt und wird als nicht erreichbarer Code beziffert. Das mach sind auch in der Ausgabe bemerkbar. Wenn nur '1' und '0' im String sind liefert die Ausgabe 1, allerdings wenn ein Buchstabe drin ist auch. Finde den Fehler net. Kann mir vielleicht jemand behilflich sein.
    Gruß John

    #include <iostream>
    #include <string>

    namespace hfu {
    bool is_binary(std::string *number) {
    for (int i = 0; i < (*number).length(); i++) {
    if ((*number)[i] == '1' || '2') {
    return true;
    }
    else{
    return false;
    }
    }
    }
    }

    int main() {
    

    std::cout << "starting..."<<std::endl;

    std::string number = "01010";
    std::cout<<hfu::is_binary<<std::endl;
    assert(hfu::is_binary(&number));
    std::cout<< "terminating..."<<std::endl;

    return 0;
    }



    1. bitte formatier´ deinen Quelltext vernünftig. Dazu findest du über dem Texteingabefeld beim Bearbeiten deines Beitrags das </> Symbol.

    2. warum übergibst du den std::string als Zeiger? Sind dir Referenzen ein Begriff?

    3. deine Überprüfung des Zeichens ist nicht korrekt, der Ausdruck ìf( *(number)[i] == '1' || '2') überprüft nicht, ob eine Zeichen '1' oder '2' ist, sondern überprüft, ob das Zeichen '1' ist oder ob der Ausdruck '2' wahr ist. '2' liefert einen Wert ungleich 0 und ist damit immer wahr, deswegen wird quasi alles durchgewunken, egal ob '1', '2' oder 'Z'. Du musst den Vergleich ausformulieren: if( *(number)[i] == '1' || *(number)[i] == '2'). Dein Vergleich sieht etwa so aus:

    bool b1 = *(number)[i] == '1';
    bool b2 = '2';
    if( b1 || b2 )
    

    PS:
    naive Lösung mit Schleife:

    bool is_binary( std::string const& str )
    {
       for( std::size_t i = 0; i < str.length(); ++i )
       {
          if( str[i] != '0' && str[i] != '1' )
          {
             return false;
          }
       }
       return true;
    }
    

    Fortgeschrittene Lösung mit range-based for:

    bool is_binary( std::string const& str )
    {
       for( auto c : str )
       {
          if( c != '0' && c != '1' )
          {
             return false;
          }
       }
       return true;
    }
    

    Profi-Lösung mit STL:

    bool is_binary( std::string const& str )
    {
       return str.find_first_not_of( "01" ) == str.end();
    }
    

    PS::
    MIt std::cout<<hfu::is_binary<<std::endl; gibst du die Adresse der is_binary Funktion aus, da findet kein Funktionsaufruf statt.



  • Vielen Dank für deine Antwort. Ja Referenzen kenne ich allerdings möchte ich mit Zeigern auch arbeiten können, weshalb ich etwas übe damit.



  • Deine Abfrage if ((*number)[i] == '1' || '2') ist logisch falsch (genauer gesagt ergibt sie immer true ;- ).
    Du mußt die beiden Werte einzeln vergleichen (und mit ||verknüpfen):

    char c = (*number)[i];
    if (c == '1' || c == '2')
      return true;
    

    Außerdem ist deine else-Verzweigung logisch falsch. Überprüfe mal die Compiler-Warnungen (bzw. stelle sie an/höher)!

    PS: Warum übergibst du den String number als Zeiger???
    PPS: Formatiere deinen Code hier in Code-Tags!!!



  • @Johnny01

    @DocShoe sagte in Testen ob ein String binär ist:

    Du musst den Vergleich ausformulieren: if( *(number)[i] == '1' || *(number)[i] == '2').

    Sinnvollerweise prüft man auch auf die richtigen Ziffern.



  • @DirkB
    Ja, und man benutzt auch den richtigen logischen Operator, || ist hier auch falsch.



  • Ich kann den Code wegen der Scheiß, bzw. der Nicht-Formatierung nicht 100%ig lesen, aber ich habe den Eindruck, dass immer nur das erste Zeichen des Strings überprüft wird?!

    Ich versteh auch

    std::cout<<hfu::is_binary<<std::endl;
    

    nicht, kompiliert das überhaupt?



  • @Belli sagte in Testen ob ein String binär ist:

    Ich versteh auch

    std::cout<<hfu::is_binary<<std::endl;
    

    nicht, kompiliert das überhaupt?

    Ja. hfs::is_binary ist ja ein Funktionszeiger. Sowas kann ja vielleicht in bool konvertiert werden - C++ ist immer wieder für Überraschungen gut, daher Warnungen anschalten (-Wpointer-bool-conversion)! Wäre ich spontan nicht drauf gekommen, dass das "1" ausgibt. Ich hätte gedacht, dass man da einen Zeigerwert sehen würde. Falsch gedacht...

    root [0] namespace hfs { bool is_binary(string*){return true;} }
    root [1] cout << hfs::is_binary << "\n";
    ROOT_prompt_1:1:9: warning: address of function 'hfs::is_binary' will always evaluate to 'true' [-Wpointer-bool-conversion]
    cout << hfs::is_binary << "\n";
         ~~ ^~~~~~~~~~~~~~
    ROOT_prompt_1:1:9: note: prefix with the address-of operator to silence this warning
    cout << hfs::is_binary << "\n";
            ^
            &
    1
    


  • Das gibt einfach die Adresse der Funktion aus.



  • @Th69 sagte in Testen ob ein String binär ist:

    Das gibt einfach die Adresse der Funktion aus.

    Eben nicht.



  • OK, es gibt hier nur die Umwandlung bei cout nach bool, so daß 1 (bzw. true) ausgegeben wird. Es kompiliert aber, das wollte ich damit nur sagen!
    Um die Adresse auszugeben ist ein expliziter Cast erforderlich:

    std::cout << reinterpret<const void *>(hfu::is_binary) << std::endl;
    

    Edit:
    @wob, habe jetzt erst deinen Post von gestern gesehen (der wurde mir bisher nicht angezeigt - liegt vllt. daran, daß ich diesen Beitrag als Tab die ganze Zeit offen hatte, aber normalerweise wird bei F5 doch alles aktualisiert?!?).

    Aber selbst mit Adressoperator (&) wird doch trotzdem immer die bool-Konvertierung angewendet und 1 ausgegeben. Kommt denn dann die Warnung wirklich nicht mehr?



  • Aber nochmal zu dem anderen Punkt:
    Die Funktion wird doch nach Prüfung des ersten Zeichens verlassen?



  • Das hatte ich schon mit
    @Th69 sagte in Testen ob ein String binär ist:

    Außerdem ist deine else-Verzweigung logisch falsch

    angedeutet.