Wie komm ich an die Bits ?



  • Aber was hat denn das bitweise UND mit dem Prüfen des letzten Bits eines Bytes zu tun ? Und wieso das letzte und nicht das erste ? 😕



  • Na ganz einfach:

    1 -> 0000 0001
    1 -> 0000 0001 UND-Verknuepft
    --------------
    0000 0001 = Das letzte bit ist gesetzt

    1 -> 0000 0001
    2 -> 0000 0010 UND-Verknuepft
    --------------
    0000 0000 = Das letzte bit ist nicht gesetzt

    mfg
    v R



  • virtuell Realisticer schrieb:

    Na ganz einfach:

    1 -> 0000 0001
    1 -> 0000 0001 UND-Verknuepft
    --------------
    0000 0001 = Das letzte bit ist gesetzt

    1 -> 0000 0001
    2 -> 0000 0010 UND-Verknuepft
    --------------
    0000 0000 = Das letzte bit ist nicht gesetzt

    mfg
    v R

    Ach soooooooooooooo ! Na klar ! Da stand ich aber voll auf dem Schlauch. Danke für eure Geduld



  • Jetzt hab ich das Programm geschrieben, aber er gibt am Ende immer noch zehn Nullen aus. Kann das vielleicht an dem while(!file.eof()) liegen ? Kommt nach dem letzten Zeichen in der Datei doch noch was ?



  • Ich habe das Gefühl, dass bei der Ausgabe hinter jedes letzte Bit eines Bytes noch eine Null gehängt wird, wieso ?



  • Clyde schrieb:

    Ich habe das Gefühl, dass bei der Ausgabe hinter jedes letzte Bit eines Bytes noch eine Null gehängt wird, wieso ?

    1.) Warum hast du das Gefühl?
    2.) Zeig doch mal Code wenn dir jemand helfen soll...



  • Das ist so die Rohversion von meinem Programm:

    #include <iostream.h>
    #include <fstream.h>
    
    int main ()
    {
    	ifstream read("datei.txt");
    	char bits[8];
    	char byte;
    
    	cout<<endl;
    	if(read!=0)
    	{
    		while(!read.eof())
    		{
    			read>>byte;
    			if(!read.fail())
    			{
    				for(int i=0;i<8;++i)
    				{
    					if(byte & 1)
    						bits[i]='1';
    					else
    						bits[i]='0';
    
    					byte>>=1;
    				}
    				for(int i=0;i<8;++i)
    					cout<<bits[i];
    			}
    			else
    			{
    				cout<<"Fehler beim Lesen der Datei !"<<endl<<endl;
    				return 1;
    			}
    
    		}
    		cout<<endl<<endl;
    	}
    	else
    	{
    		cout<<"Datei nicht gefunden !"<<endl<<endl;
    	}
    
    return 0;
    }
    


  • Nu nimmste mal dein Visual C++ oder was du auch immer als Programmierumgebung hast, und schmeisst den Debugger an. Lies mal den Verlinkten Artikel zum Thema Debuggen. Ist zwar Borlandspezifisch aber die Vorgehensweisen sind in jeder IDE realtiv ähnlich.

    noch ne Anmerkung zu JFK's Code: Im Prinzip wärs eleganter die Bitmaske statt der Daten zu shiften, da dann die Ursprungsdaten nicht zerstört werden.

    -junix



  • Nö, ist doch im Prinzip richtig (mal abgesehen davon, dass es nicht kompilieren wird)

    Schreibe oben anstatt...

    #include <iostream.h>
    #include <fstream.h>
    

    ...einfach...

    #include <iostream>
    #include <fstream> 
    using namespace std;
    

    Und siehe da, es kompiliert.



  • @junix: da haste wohl recht. Aber es sollte ja einfach sein und nicht elegant.



  • MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ausserdem wärs eleganter, das char-Array um 1 Element zu erhöhen, mit Null zu initialisieren (memset) und dann die String-Operationen zu verwenden für die Ausgabe (o:

    @JFK: Elegant <> Not(Einfach) (o:
    Ne im ernst, das Schieben der Maske hätte die Lösung nicht zwingend verkompliziert (o:

    -junix



  • junix schrieb:

    MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ist doch Jacke wie Hose ob ich in diesem Fall bei BuiltIns ein pre increment oder ein post increment mache (C++ FAQ).

    The for statement:
    
    for(for-init-statement; conditionopt ; expressionopt)
    {
      statement
    }
    
    is equivalent to:
    
    {
      for-init-statement
      while(condition)
      {
        statement
        expression
      }
    }
    

    Es dürfte also (in diesem Fall bei built-ins) nichts ausmachen 😉 . btw gibt das Programm bei mir keine 0 zuviel aus.



  • MaSTaH schrieb:

    junix schrieb:

    MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ist doch Jacke wie Hose ob ich in diesem Fall bei BuiltIns ein pre increment oder ein post increment mache (C++ FAQ).

    The for statement:
    
    for(for-init-statement; conditionopt ; expressionopt)
    {
      statement
    }
    
    is equivalent to:
    
    {
      for-init-statement
      while(condition)
      {
        statement
        expression
      }
    }
    

    Hmmm stimmt, hatte mich da vertan.

    -junix



  • Hab sowas auch schonmal geschrieben:

    #include <iostream.h>
    #include <fstream.h>
    #include <math.h>
    
    int main()
    {
       char buff,bits[8];
       ifstream datei("datei.txt");
       if(datei)
       {
          while(!datei.eof())
          {
             datei>>buff;
             if(!datei.eof())
             {
                for (int i=0;i<=7;i++)
                {
                   if(buff-pow(2,7-i)>=0)
                   {
                      buff-=pow(2,7-i);
                      bits[i]='1';
                   }
                   else bits[i]='0';
                   cout << bits[i];
                }
                cout << endl;
             }
          }
       }
       else cout << "Dateifehler !";
       datei.close();
       return 0;
    }
    


  • Danke für diesen Beitrag. Das ist aber so ziemlich das unperformanteste.... Bei Binärzahlen brauch ich doch kein POW!?!?!? Da schieb ich die Bits und gut ist. Jede Bitverschiebung nach links entspricht einem ^2.



  • Leute ihr müsst mir nochmal helfen. Ich hab ein bisschen nachgedahct, aber diese eine Schleife verstehe ich immer noch nicht richtig:

    for(int i=0;i<8;++i)
    {
        if(byte & 1)
            bits[i]='1';
        else
            bits[i]='0';
    
        byte>>=1;
    }
    

    1.: Wieso wird mit if(byte & 1) gerade das letzte Bit eines Bytes auf 1 geprüft ?

    2.: Was genau macht byte>>=1 ? Was wandert da wohin ?



  • Ich hab hier mal ne etwas andere Version des Programms. Es liest eine beliebige Datei ein und schreibt dann für jedes Zeichen das ihm folgende Zeichen in temp.txt. Aber es funktioniert nicht, sondern führt beim Ausführen zu "Fehler beim Lesen der Datei !". Wieso ?

    #include <iostream>
    #include <fstream>
    
    int main (int argc, char* argv[])
    {
    	using namespace std;
    
    	ifstream read(argv[1]);
    	ofstream write("temp.txt");
    	char byte;
    	int add;
    
    	cout<<endl;
    	if(read)
    	{
    		while(!read.eof())
    		{
    			read>>byte;
    			if(!read.fail())
    			{
    				if(int(byte)==255)
    					add=33;
    				else
    					add=int(byte)+1;
    
    				byte=char(add);
    				write<<byte;
    			}
    			else
    			{
    				cout<<"Fehler beim Lesen der Datei !"<<endl<<endl;
    				return 1;
    			}
    
    		}
    		cout<<endl<<endl;
    	}
    	else
    	{
    		cout<<"Datei nicht gefunden !"<<endl<<endl;
    	}
    
    return 0;
    }
    


  • 1.: Wieso wird mit if(byte & 1) gerade das letzte Bit eines Bytes auf 1 geprüft ?

    Dezimal 1 = hexadezimal 0x01 = binär 00000001

    Wenn ich also frage, ob die AND-Verknüpfung von byte und binär 00000001 = TRUE (=1) ist, dann führt das dazu, daß nur das niedrigste (das rechteste) Bit geprüft wird. Alle anderen Bits der Vergleichsmaske 00000001 sind ja 0 und können daher niemals 1 ergeben, weil

    1 AND 0 = 0
    0 AND 1 = 0
    1 AND 1 = 1

    ist. Die Aufgabe ist es ja, jeweils ein Bit daraufhin zu prüfen, ob es gesetzt ist oder nicht.

    2.: Was genau macht byte>>=1 ? Was wandert da wohin ?

    [/quote]
    Dieser Ausdruck ist der zweite Teil des Spiels. Zuvor hab ich ja das niedrigste Bit geprüft. Nun hab ich das getan und würde mir gerne auch die restlichen 7 Bits ankucken. Deshalb hab ich mich dazu entschieden, alle Bits in dem zu betrachtenden Byte um eine Stelle nach rechts zu bewegen. Das macht der ">>" Operator. Das ist praktisch das gleiche, wie wenn Du die dezimale 123 durch 10 dividierst. Was passiert hier? Die Zahl wird um eine Dezimalstelle nach rechts bewegt und das Komma um 1 Stelle nach links verschoben, wie das Ergebnis 12,3 eindrucksvoll zeigt.
    Da es bei int bzw. char Werten keine Nachkommastelle gibt, fällt das unterste Bit einfach weg und verschwindet im Nirgendwo.

    Also aus binär
    1001001101 wird nach >>= 1 der neue Binärwert
    0100100110.

    Ansonsten empfehle ich dringend das Studium passender Bücher über die C++ Sprache. Dort wird sowas auch erklärt und hilft, bessere Programme zu schreiben (wie das obige Beispiel mit pow() gezeigt hat, hat die Sache mit der Bitschieberei nicht jeder so richtig verstanden).



  • Vielen Dank für die ausführliche (und verständliche) Erklärung. Ich lerne aus einem Buch ("Objektorientiertes Programmieren in C++" von Nicolai Josuttis), aber da steht das leider so nicht drin. Also danke nochmal.

    Weiß einer wieso es bei dem abgeänderten Programm zu "Fehler beim Lesen der Datei !" kommt ?



  • Also ehrlich gesagt, hab ich das mit dem bitweisen AND und OR früher (so um 1830 herum) 😉 auch nie wirklich richtig verstanden, bis ich auf dem C64 mit Assembler begonnen hatte. Da war's dann plötzlich urklar.

    Deshalb kann man in C/C++ auch Multiplikationen/Divisionen mit 2, 4, 8, 16, 32, 64, 128 etc. dadurch umgehen, daß man die betreffende Zahl einfach x mal nach links (Multiplikation) bzw. rechts (Division) shiftet. Das macht die CPU deutlich schneller, als multiplizieren oder dividieren. Kann aber sein, daß der Compiler das bei seinen Optimierungen selber erkennt und macht (geht natürlich nur, wenn Konstante im Spiel sind und nich Variablen).

    Zu Deinem anderen Problem: Dir ist klar, daß Du eine Datei lesen willst, deren Name Du dem Programm als Parameter mitgeben mußt?


Anmelden zum Antworten