Frage zu Schleife



  • Hallo ich hab eine Frage zu der Schleife.

    Den Source Code hab ich hier im Forum gefunden.
    Dort gibt man ja eine Binärzahl ein und eine Dezimalzahl kommt wieder raus.

    Nur irgendwie versteh ich nicht das was hier passiert:

    for (wert=i=0; bin[i] ; i++)
    wert=wert*2+bin[i]-48;

    Wenn ich jetzt z.b. 111 eingebe wie würde das dann hier aussehen?
    wert=wert*2+bin[i]-48;

    #include <iostream>
    using namespace std;
    #include <conio.h>
    
    void main()
    {
      char bin[256];
      long int wert;
      int i = 0;
    
      clrscr();
    
      cout<<"Geben Sie die binäre Zahlendarstellung ein: ";
      cin>>bin;
    
        for (wert=i=0; bin[i] ; i++)
    
        wert=wert*2+bin[i]-48;
    
      cout<<"Dezimaler Wert: "<<wert;
      getch();
    }
    


  • fragefrage schrieb:

    Nur irgendwie versteh ich nicht das was hier passiert:

    for (wert=i=0; bin[i] ; i++)
    wert=wert*2+bin[i]-48;

    Wenn ich jetzt z.b. 111 eingebe wie würde das dann hier aussehen?
    wert=wert*2+bin[i]-48;

    Im Schleifenkopf werden zu Beginn die Variablen wert und i mit 0 initialisiert. Die Abbruchbedingung - bin[i] - hat also zu Beginn den Wert des ersten Zeichens des char-Arrays bin.
    In Deinem Beispiel 111 also '1' (Ascii 49).
    Im vierten Schleifendurchlauf steht sie dann wegen i++ in jedem Durchlauf auf dem Stringterminierenden Nullzeichen, was zum Abbruch der Schleife führt.
    Naja, und bei jedem Schleifendurchlauf wird wert wie dargestellt berechnet, wobei es wie gesagt anfangs den Wert 0 hat, dann aber den in bisherigen Durchläufen ermittelten Wert. bin[i] - 48 macht einfach aus dem Zeichen '1' den Zahlenwert 1, bzw. würde aus dem Zeichen '0' (Ascii 48) den Zahlenwert 0 machen.



  • Hier wird eine Schleife solange ausgeführt, bis bin[i]==0 ist (binäre Null steht ja für's String-Ende). Und darin wird eben jede binäre Stelle umgerechnet, wobei hier quasi von hinten (links) nach vorne (rechts) vorgegangen wird. Jede Stelle wird erstmal mit einer Eertigkeit 1 behandelt und im nächsten Schleifendurchlauf sozusagen im Rang erhöht und entsprechend multipliziert. Wenn dir der Ausdruck zu kompliziert ist, dann zerlege ihn doch in mehrere Zeilen und gehe schrittweise mit dem Debugger durch.



  • Danke für die Antworten.

    Also steht die 48 dafür um aus '1' den Zahlenwert 1 zu machen ?



  • Klar, weil 1 im char den dezimalwert 49 hat... würd ich jetzt so einfach mal behaupten, aber nachgeschaut hab ich nicht...



  • Gustl schrieb:

    Klar, weil 1 im char den dezimalwert 49 hat... würd ich jetzt so einfach mal behaupten, aber nachgeschaut hab ich nicht...

    Na klar, 48-57 sind die Ziffern.



  • Wenn man - '0' anstelle von - 48 schreibt, ist es auch verständlicher.



  • Fellhuhn schrieb:

    Wenn man - '0' anstelle von - 48 schreibt, ist es auch verständlicher.

    Na ja, wenn man wie ich (und wahrscheinlich du) die ASCII-Codes sowieso kennt, macht's in meinen Augen keinen Unterschied. Ich schreibe sogar lieber den Wert statt des Charakters. Geschmacksache. Auf Dauer ist es auch ratsam, zumindest einige auswendig zu lernen (10,13,27,32,48-,65-,97-,usw.), da hilft die Verwendung im eigenen Code u.U. Und wenn jemand sich so gar nicht damit auskennt, wird er vermutlich auch nicht verstehen, wieso man jetzt das Zeichen '0' subtrahieren muss...



  • "Magic Numbers" sollten wo es geht vermieden werden. Wenn man keine Ahnung vom Aufbau der Ascii-Tabelle hat, ist es mE verständlicher von einem char einen anderen char abzuziehen als auf einmal noch ints mit in die Berechnung einzubeziehen. Für Leute die wissen was man da tut sicherlich eine Geschmacksfrage.



  • Wo kann man das den noch genauer nach lesen, so was man das auch versteht?^^



  • fragefrage schrieb:

    Wo kann man das den noch genauer nach lesen, so was man das auch versteht?^^

    Was genau denn? Also eine ASCII-Tabelle findest du überall, z.B. hier: http://www.asciitable.de/tabelle.html

    Jedes Zeichen (druckbare und nicht druckbare) entspricht einem Zahlencode in der ASCII-Tabelle, so wie die '0' eben gleich 48 ist. Ein Leerzeichen ist ne 32, wenn du auf deine ESC-Taste drückst, ist das der Code 27, ein 'A' ist die 65 usw. Du kannst das in einem Texteditor/Word/sonstwas ausprobieren: halte die ALT-Taste gedrückt und gib währenddessen eine 4 und eine 8 ein. ALT-Taste loslassen... tada! Es wird an die Cursorposition eine '0' geschrieben. In C/C++ ist die Grenze zwischen char und int ziemlich dünn (anders, als in Sprachen wie Basic), sie werden lediglich etwas anders interpretiert. Aber du kannst mit chars genauso rechnen wie mit ints, da ein char letztlich auch nur ein Ganzzahlenwert ist.
    Im Beispiel sieht es ja so aus, dass aus einem Zeichen '0', also char(48), der Wert 48 gemacht werden soll. Deshalb müssen eben 48 abgezogen werden...



  • Hi fragefrage,

    auch wenn das die Frage nicht beantwortet.... aber was ist aus dem guten, alte

    #include <iostream>
    using namespace std;
    
    int main() {
      long int wert;
    
      cout<<"Geben Sie die binäre Zahlendarstellung ein: ";
      cin>> hex >> wert;
      cout<<"Dezimaler Wert: "<<wert;
      return 0;
    }
    

    geworden ?
    😉

    Also der Code, den Du da gefunden hast, ist nicht gerade ein Beispiel für guten Code (falsche main()-Signatur, non-Std-Funktionen, unnötige Portabilitätseinschränkungen (ASCII), ...) ...
    ...vielleicht solltest Du Dich nicht allzu lange mit ihm beschäftigen.

    Gruß,

    Simon2.



  • Es ging um die Eingabe von binären, nicht hexadezimalen, Werten. Ansonsten aber ein schönes Beispiel. 😉



  • Schade das die STL nur eine komfortable Ausgabe von binären Daten (als String) erlaubt und keine für die die Eingabe...

    #include <bitset>
    #include <iostream>
    
    int main(int argc, char*argv[]){
       int t;
       std::cin >> t;
       std::cout << "in binär: " << std::bitset<32>(t).to_string() << std::endl;  
    }
    


  • _matze schrieb:

    Es ging um die Eingabe von binären, nicht hexadezimalen, Werten. Ansonsten aber ein schönes Beispiel. 😉

    😮 🙄
    OK - hatte aus "Binärzahl" -> "Binärdaten" -> "Hexzahlen" gelesen.

    Tja - falsch eben.

    Gruß,

    Simon2.



  • _matze schrieb:

    fragefrage schrieb:

    Wo kann man das den noch genauer nach lesen, so was man das auch versteht?^^

    Was genau denn? Also eine ASCII-Tabelle findest du überall, z.B. hier: http://www.asciitable.de/tabelle.html

    Jedes Zeichen (druckbare und nicht druckbare) entspricht einem Zahlencode in der ASCII-Tabelle, so wie die '0' eben gleich 48 ist. Ein Leerzeichen ist ne 32, wenn du auf deine ESC-Taste drückst, ist das der Code 27, ein 'A' ist die 65 usw. Du kannst das in einem Texteditor/Word/sonstwas ausprobieren: halte die ALT-Taste gedrückt und gib währenddessen eine 4 und eine 8 ein. ALT-Taste loslassen... tada!

    Das geht allerdings nur mit den Ziffern auf dem Nummernblock!



  • Fellhuhn schrieb:

    Schade das die STL nur eine komfortable Ausgabe von binären Daten (als String) erlaubt und keine für die die Eingabe...

    #include <bitset>
    #include <iostream>
    
    int main(int argc, char*argv[]){
       int t;
       std::cin >> t;
       std::cout << "in binär: " << std::bitset<32>(t).to_string() << std::endl;  
    }
    

    Das kann man aber echt leicht bauen:

    template<size_t size>
    std::ostream& operator<<(std::ostream& ostr, const std::bitset<size>& set)
    {
        ostr << set.to_string();
        return ostr;
    }
    
    template<size_t size>
    std::istream& operator>>(std::istream& istr, std::bitset<size>& set)
    {
        std::string input;
        istr >> input;
        try
        {
            std::bitset<size> tmp(input);
            set = tmp;
        }
        catch(...)
        {
            istr.setstate(std::ios::failbit);
        }
        return istr;
    }
    

    Nur so hingeklatscht.



  • [borat]
    naaaaaiiiissss
    [/borat]
    👍 😋

    Jetzt wäre nur noch die Frage, ob man das direkt in einen Manipulator á la hex umpulen könnte, mit dem man dan direkt in ein long lesen kann.
    Vielleicht mit einem wrapper (z.B. "bin"), in den man mittels operator>>(istream&, bin&) einliest und der dann einen eigenen operator>>(bin const&, T&) für verschiedene Typen anbietet ?
    Aber damit geht dann irgentwie der istream-Parameter flöten und man kann nicht mehr "anhängen", .... hmmmmmmm.
    Muss mal nachsehen, wie std::hex das macht.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    ...

    Meinst Du sowas:

    unsigned long a;
        std::cin >> std::hex >> a;
    

    ??
    Das geht doch so schon.

    Edit:
    Achso, bezogen auf bin. Okay.



  • Ich versuch das gerade mal aufm Papier auszurechnen ....

    Aber ohne Erfolg 😞

    Die Eingabe soll sein: 101

    Das Ergebniss wäre ja dann 5

    cout<<"Geben Sie die binäre Zahlendarstellung ein: ";
      cin>>bin;
    
    for (wert=i=0; i<3 ; i++)
    
      wert=wert*2+bin[i]-48;
    

    Für die erste Zahl:
    Aber das ist denk ich mal falsch _
    wert = 0 * 2 + 1 ??*-+ 1?? -48


Log in to reply