Wie komm ich an die Bits ?
-
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 = 1ist. 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?
-
JFK schrieb:
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
Was allerdings jetzt nicht heissen soll, dass man Multiplikationen in Zukunft statt mit "Var * 2" mit "Var <<= 2" codieren soll. Derartige Optimierungen übernehmen schon die billigsten Compiler. Ausserdem ist der Geschwindigkeitsvorteil im Vergleich zur Unlesbarkeit des Quelltextes minimal.
-junix
-
Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt. Wenn ich nur die Binärwerte eines Zeichens WORDs oder Doppelworts haben möchte schreibe ich doch nicht alles Neu, oder ?
Joe
-
JoeIntel schrieb:
Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt.
Hamma ned, wieso?
-junix
-
junix schrieb:
JoeIntel schrieb:
Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt.
Hamma ned, wieso?
-junix
Ach das war C++ Code was hier bis jetzt abgeliefert wurde , also bis auf cin war das nicht wirklich zu erkennen. Es gibt aber auch klassen die so etwas implementieren wenn ich mich nicht irre und die greifen dann auch auf itoa zu. Man ist nur ein bisschen elitärer als wenn mans gleich benutzt.
Joe
-
Ich wüsste nicht, wo mir bei der Lösung des gestellten Problem itoa eine einfachere lösung sein sollte als die AND-Verknpüfung? Ich lass mir aber gern die Augen öffnen, wenn du was im Petto hast, lass und doch bitte Teilhaben...
-junix
-
junix schrieb:
Ich wüsste nicht, wo mir bei der Lösung des gestellten Problem itoa eine einfachere lösung sein sollte als die AND-Verknpüfung? Ich lass mir aber gern die Augen öffnen, wenn du was im Petto hast, lass und doch bitte Teilhaben...
-junix
nun ja ich für meinen Teil denek das es einige Vorteile dieser Funktion gibt. Die Frage war es doch wie bekomme ich die Bits ausgegeben und nicht wie schreibe ich eine tolle Funktion um die Bits auszugeben. Dies mach itoa perfekt und ausserdem für grössere eiheiten als Byte ich kann mir also vielleicht einige Schleifen sparen. Zweites vermeide ich Fehlerquellen wenn ich Funktionen aus Standardbibliotheken verwenden und kann davon ausgehen das diese auch optimiert sind. Wir sehen ja alle wie viele Fehler sich in diesem kurzen Stück Code einschleichen können und wie viele ansätze es gibt. Und drittens und nicht zu leztzt ist es kürzer einfacher und einfacher zu handhaben bzw. zu lesen.
Dies alles sagt nichts über die Qualität eures Codes aus und ich will mir auch nicht erlauben ihn zu kritisieren aber es ist schon etwas länger als itoa(byte,ziel,2); oder von mir aus auch QString:arg(byte,0,2) ?
Joe