2008-11-05 10 views
6

Ich lerne C++ und schreibe kleine Programme, während ich mitfahre. Im Folgenden ist ein solches Programm:Endlosschleife in C++

// This program is intended to take any integer and convert to the 
// corresponding signed char. 

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(true){ 
    std::cin >> n; 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

Als ich dieses Programm ausführen und halten Eingänge relativ klein absolute Werte, verhält es sich wie erwartet. Wenn jedoch größere Eingaben eingegeben werden, z. B. 10000000000, spuckt das Programm wiederholt die gleiche Ausgabe aus. Einige Kombinationen von Eingaben verursachen unberechenbares Verhalten. Zum Beispiel:

#: ./int2ch 
10 
10 --> 

10000000000 
10 --> 

10 --> 

10 --> 

10 --> 

Das Programm spuckt "10 ->", bis es getötet. (Bei dieser speziellen Sequenz von Eingängen ändert sich die Ausgabe des Programms sprunghaft.) Ich habe auch bemerkt, dass die Ausgabe großer Werte durch die vorherige legale Eingabe sowie den Wert der aktuellen illegalen Eingabe bestimmt wird.

Was ist los? (Ich kümmere mich nicht darum, das Programm zu reparieren, das ist einfach. Ich will es verstehen.)

Antwort

13

Im Grunde befindet sich Ihr cin Stream in einem Fehlerzustand und kehrt daher sofort zurück, wenn Sie versuchen, es zu lesen. Rewrite Ihr Beispiel wie folgt aus:

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(std::cin >> n){ 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

cin >> n einen Verweis auf cin zurück, die Sie für „gut-ness“ in einem bedingten testen können. Also im Grunde die "while(std::cin >> n)" sagt "während ich konnte noch aus der Standard-Eingabe erfolgreich lesen, tun Sie die folgenden"

EDIT: der Grund, dass es wiederholt den letzten guten Wert eingegeben ist, weil das war der letzte Wert erfolgreich eingelesen n, liest die gescheiterte nicht den Wert von n ändern

EDIT: wie in einem Kommentar erwähnt, können Sie den Fehlerzustand löschen und versuchen Sie es erneut so etwas wie dies würde wahrscheinlich funktionieren und nur schlechte Zahlen ignorieren:

#include <iostream> 
#include <climits> 

int main() { 
    signed char sch = 0; 
    int n = 0; 
    while(true) { 
     if(std::cin >> n) { 
      sch = n; 
      std::cout << n << " --> " << sch << std::endl; 
     } else { 
      std::cin.clear(); // clear error state 
      std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it 
     } 
    } 
} 
+0

Alternativ rufen Sie std :: cin.clear() auf, um den Fehlerzustand vor dem nächsten Durchlauf der Schleife zu entfernen. – hark

3

Vorausgesetzt, dass Sie auf einer 32-Bit-Maschine sind, ist 10000000000 eine zu große Zahl, um durch eine int dargestellt werden. Wenn Sie ein int in ein char umwandeln, erhalten Sie abhängig vom Compiler nur 0..255 oder -128..127.

+0

Das ist 0..255 oder -128..127, eigentlich. :) – unwind

0

Ein Problem hier ist, dass ein char eine Größe von einem Byte hat und somit kann Halten Sie nur eine Zahl zwischen -127 und 128. Ein int auf der anderen Seite ist in der Regel 4 Bytes und kann viel größere Werte annehmen. Das zweite Problem ist, dass Sie einen Wert eingeben, der selbst für einen int zu groß ist.

+0

Erstens ist das Drucken von "einigen seltsamen Zeichen" nicht die Ursache, zweitens ist ein Zeichen NICHT standardmäßig signiert, dies ist compilerabhängig. Es ist * oft * signiert, muss aber nicht sein. –

5

Ja, Evan Teran wies bereits auf die meisten Dinge hin. Eine Sache, die ich hinzufügen möchte (da ich seinen Kommentar noch nicht kommentieren kann :)) ist, dass Sie den Aufruf auf istream :: clear vor den Aufruf an istream :: ignore setzen müssen. Der Grund ist, dass istream :: ignore ebenfalls nichts tun wird, wenn sich der Stream noch im fehlgeschlagenen Zustand befindet.

+0

Danke, korrigiert. Dafür bekommst du eine Aufwertung;) –