Du meinst, weil z.B. bei einer Eingabe von 200 sowas angezeigt wird:
200
401
803
1606
...
Wenn ja: Das liegt an
int muster;
Die Größe von Variablen des Typs int ist implementierungsabhängig (ebenso, ob char ohne unsigned davor signed oder unsigned ist); bei aktuellen (PC-)Compilern sind es 4 Byte, bei älteren 2 Byte. Du geht aber davon aus, dass muster 1 Byte groß ist.
Als Beispiel der erste Schritt für 200:
muster = 11001000 (200)
muster<<=1; -> 10010000 (144) (1 ist rausgefallen, da->muster' nur 8 Bit groß ist)
if(alt&128) // Ja, also:
muster = muster + 1; -> 10010001 (145)
Stimmt.
'muster' ist aber bei dir mindestens 2 Byte (16 Bit) groß:
muster = 0000000011001000 (200)
muster<<=1; -> 0000000110010000 (400)
(da ja bei 2 oder mehr Byte bei einem Wert von 200 genug Platz ist und nichts rausfällt)
if(alt&128) // Ja, also:
muster = muster + 1; -> 0000000110010001 (401)
Der Wert wird immer größer, bevor überhaupt später mal bei der Shift-Operation (<<=1)
das erste Bit rausfällt. Nach 8 Durchgängen ziehst du dann von der riesigen Zahl
256 ab (muster = muster - 256), was aber auch nichts mehr hilft.
Bei 1 funktioniert es deswegen:
0000000000000001
0000000000000010
0000000000000100
0000000000001000
0000000000010000
0000000000100000
0000000001000000
0000000010000000
0000000100000000 -> 256! Dürfte bei nur 8 Bit gar nicht passieren, du bist hier schon im nächsten Byte.
muster = 256 + 1 = 257
Dann nach der inneren Schleife:
muster = 257 - 256 = 1
Trotz des Fehlers stimmt es dann wieder.
Bei 2 klappt es nicht mehr, da das gesetzte Bit schon bei der vorletzten Shift-Operation übers Ziel hinausschießt.
Eigentlich ist int ein Typ mit Vorzeichen, d.h., irgendwann wird sogar eine negative Zahl angezeigt; aber das spielt jetzt keine Rolle.
---------------
Du könntest einen angemessenen Datentypen (mit korrekter Größe und ohne Vorzeichen) benutzen, also unsiged char statt int - und die Eingabe etwas verändern, ich erkläre unten noch, warum - dann kannst du den Rest des Programms so lassen wie er ist.
Mögliche Lösung (du kannst es natürlich auch anders machen):
Ersetze
durch
Code:
unsigned char muster, alt;
int musterIn;
und
durch
Code:
cin >> musterIn;
// Zu große Zahl oder andere unsinnige Eingabe?
if (musterIn > 255) {
musterIn= 255;
cout << Verwendeter Wert: << musterIn << endl;
}
// Sichere Typumwandlung: musterIn ist jetzt mindestens 0, maximal 255
muster= (unsigned char) musterIn;
-
(Hinweis: Ich weiss nicht, welchen Compiler du verwendest, es könnte evtl. auch anders sein bei unsigned char)
Sinn: bei cin >> irgendwas wird intern der entsprechende Datentyp angenommen (der Operator >> ist überladen [er hat übrigens nichts mit den Shift-Operatoren zu tun]), und das ist bei->char'- und->unsigned char'-Typen ein Textzeichen (ASCII-Charakter).
Damit es gleich stimmt, wird ein->int' zum Einlesen genommen, der Wert geprüft und dann der Variable
muster zugewiesen. Sonst bekommst du z.B. bei einer Eingabe von 1 nicht den Wert 1, sondern den Code für das Textzeichen 1. Man kann hier aber z.B. auch ein->unsigned char' direkt einlesen und dann eine Konstante abziehen, damit der echte Wert in muster steht. Allerdings kann man den Wert dann nicht mehr wirklich prüfen.
Übrigens muss nur getestet werden, ob musterIn > 255, da wegen des Typs unsigned int erst gar keine negativen Werte vorkommen können, ganz egal, welcher Unsinn als Muster eingetippt wird.
Da auch der Operator << ein->unsigned char' als Textzeichen interpretiert, musst du den Wert zum
Anschauen in einen anderen Typ umwandeln, sonst siehst du nur merkwürdige Zeichen.
Z.B.
Code:
cout << (int)muster << endl;
oder
Aber ich würde alles auf cout umstellen ... Beispiel:
Code:
cout << \t\t\t Lauflicht auf Relaiskarte \n\n\n;
Die doppelte Pause nach einem kompletten Durchlauf durch das zweite Sleep(1000) ist sicher Absicht?
Es sollte dann eigentlich soweit funktionieren.
-------------
Du meinst, weil z.B. bei einer Eingabe von 200 sowas angezeigt wird:
200
401
803
1606
...
Wenn ja: Das liegt an
int muster;
Die Größe von Variablen des Typs int ist implementierungsabhängig (ebenso, ob char ohne unsigned davor signed oder unsigned ist); bei aktuellen (PC-)Compilern sind es 4 Byte, bei älteren 2 Byte. Du geht aber davon aus, dass muster 1 Byte groß ist.
Als Beispiel der erste Schritt für 200:
muster = 11001000 (200)
muster<<=1; -> 10010000 (144) (1 ist rausgefallen, da->muster' nur 8 Bit groß ist)
if(alt&128) // Ja, also:
muster = muster + 1; -> 10010001 (145)
Stimmt.
'muster' ist aber bei dir mindestens 2 Byte (16 Bit) groß:
muster = 0000000011001000 (200)
muster<<=1; -> 0000000110010000 (400)
(da ja bei 2 oder mehr Byte bei einem Wert von 200 genug Platz ist und nichts rausfällt)
if(alt&128) // Ja, also:
muster = muster + 1; -> 0000000110010001 (401)
Der Wert wird immer größer, bevor überhaupt später mal bei der Shift-Operation (<<=1)
das erste Bit rausfällt. Nach 8 Durchgängen ziehst du dann von der riesigen Zahl
256 ab (muster = muster - 256), was aber auch nichts mehr hilft.
Bei 1 funktioniert es deswegen:
0000000000000001
0000000000000010
0000000000000100
0000000000001000
0000000000010000
0000000000100000
0000000001000000
0000000010000000
0000000100000000 -> 256! Dürfte bei nur 8 Bit gar nicht passieren, du bist hier schon im nächsten Byte.
muster = 256 + 1 = 257
Dann nach der inneren Schleife:
muster = 257 - 256 = 1
Trotz des Fehlers stimmt es dann wieder.
Bei 2 klappt es nicht mehr, da das gesetzte Bit schon bei der vorletzten Shift-Operation übers Ziel hinausschießt.
Eigentlich ist int ein Typ mit Vorzeichen, d.h., irgendwann wird sogar eine negative Zahl angezeigt; aber das spielt jetzt keine Rolle.
---------------
Du könntest einen angemessenen Datentypen (mit korrekter Größe und ohne Vorzeichen) benutzen, also unsiged char statt int - und die Eingabe etwas verändern, ich erkläre unten noch, warum - dann kannst du den Rest des Programms so lassen wie er ist.
Mögliche Lösung (du kannst es natürlich auch anders machen):
Ersetze
durch
Code:
unsigned char muster, alt;
int musterIn;
und
durch
Code:
cin >> musterIn;
// Zu große Zahl oder andere unsinnige Eingabe?
if (musterIn > 255) {
musterIn= 255;
cout << Verwendeter Wert: << musterIn << endl;
}
// Sichere Typumwandlung: musterIn ist jetzt mindestens 0, maximal 255
muster= (unsigned char) musterIn;
-
(Hinweis: Ich weiss nicht, welchen Compiler du verwendest, es könnte evtl. auch anders sein bei unsigned char)
Sinn: bei cin >> irgendwas wird intern der entsprechende Datentyp angenommen (der Operator >> ist überladen [er hat übrigens nichts mit den Shift-Operatoren zu tun]), und das ist bei->char'- und->unsigned char'-Typen ein Textzeichen (ASCII-Charakter).
Damit es gleich stimmt, wird ein->int' zum Einlesen genommen, der Wert geprüft und dann der Variable
muster zugewiesen. Sonst bekommst du z.B. bei einer Eingabe von 1 nicht den Wert 1, sondern den Code für das Textzeichen 1. Man kann hier aber z.B. auch ein->unsigned char' direkt einlesen und dann eine Konstante abziehen, damit der echte Wert in muster steht. Allerdings kann man den Wert dann nicht mehr wirklich prüfen.
Übrigens muss nur getestet werden, ob musterIn > 255, da wegen des Typs unsigned int erst gar keine negativen Werte vorkommen können, ganz egal, welcher Unsinn als Muster eingetippt wird.
Da auch der Operator << ein->unsigned char' als Textzeichen interpretiert, musst du den Wert zum
Anschauen in einen anderen Typ umwandeln, sonst siehst du nur merkwürdige Zeichen.
Z.B.
Code:
cout << (int)muster << endl;
oder
Aber ich würde alles auf cout umstellen ... Beispiel:
Code:
cout << \t\t\t Lauflicht auf Relaiskarte \n\n\n;
Die doppelte Pause nach einem kompletten Durchlauf durch das zweite Sleep(1000) ist sicher Absicht?
Es sollte dann eigentlich soweit funktionieren.
// Edit
Noch zur Erlärung: In muster= (unsigned char) musterIn ist hier eigentlich die Angabe der gewünschten Konvertierung als (unsigned char) [-> cast] nicht unbedingt nötig, da der Compiler den Wert auch automatisch umwandelt. Aber es ist erstens übersichtlicher, da du dann dem Code sofort ansiehst, dass eine Typumwandlung stattfindet, zweitens verhindert es Warnungen des Compilers in höheren Warnstufen. Diese Warnung wäre hier unsinnig, da du ja weisst, dass musterIn einen Wert zwischen 0 und 255 hat und deswegen auf jeden Fall ohne Veränderung des Wertes in ein unsigned char, also 1 Byte passt, das ja Werte zwischen 0 und 255 aufnehmen kann.
Alternativ (in C++ besser und üblich) kannst du hier statt des C-Casts auch muster= static_cast<unsigned char>(musterIn); verwenden.
Noch ein Vorschlag: Vermeide magische Zahlen in deinen Programmen. Also z.B. oben im Code
Code:
const int ASCII_Esc= 27;
const unsigned short Druckerport= 0x378;
und dann
Code:
while (taste != ASCII_Esc);
Code:
outp(Druckerport, muster);
usw.
Noch eine Kleinigkeit: Deinem Programm ist es egal, welche Taste gedrückt wird, da die Schleife in
if(kbhit())
{
taste = getch();
break;
}
bei einem Tastendruck so oder so verlassen wird und die Bedingung in der do-while-Schleife dann keine Rolle mehr spielt. Du könntest z.B. das->break' entfernen oder diese Abfrage in die innere (die for-)Schleife setzen. Dann kann man das Programm auch schneller abbrechen.