2008-11-05 28 views
6

Uczę się języka C++ i piszę małe programy, kiedy się z nimi zgadzam. Poniżej zamieszczona jest jeden taki program:nieskończona pętla w 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; 
    } 
} 

Kiedy uruchomić ten program i utrzymanie nakładów na stosunkowo małych wartościach bezwzględnych, to zachowuje się zgodnie z oczekiwaniami. Ale kiedy wprowadzę większe wejścia, np. 10000000000, program będzie powtarzalnie wyprowadzał to samo wyjście. Niektóre kombinacje wprowadzania powodują błędne zachowanie. Na przykład:

#: ./int2ch 
10 
10 --> 

10000000000 
10 --> 

10 --> 

10 --> 

10 --> 

Program wypluwa "10 ->", dopóki nie zostanie zabity. (Przy tej konkretnej sekwencji wejść wyjście programu zmienia się niepoprawnie.) Zauważyłem również, że wynik dużych wartości jest określony przez poprzedni legalny sygnał wejściowy, a także wartość bieżącego nielegalnego wejścia.

Co się dzieje? (Nie dbam o naprawianie programu, to jest łatwe. Chcę to zrozumieć.)

Odpowiedz

13

Zasadniczo Twój strumień cin znajduje się w stanie awarii, a więc natychmiast zwraca się, gdy spróbujesz go odczytać. Przepisać przykład tak:

#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 powróci odniesienie do cin, który można przetestować dla „good-Ness” w ramach warunkowego. Tak więc w zasadzie "while(std::cin >> n)" mówi "podczas gdy mogłem nadal czytać ze standardowego wejścia z powodzeniem, wykonaj następujące czynności:" EDYCJA: powodem, dla którego wielokrotnie wyprowadzana jest ostatnia dobra wartość, ponieważ była to ostatnia wartość poprawnie odczytana w n, nieudane czyta nie zmieni wartość n

EDIT: jak zauważono w komentarzu, można wyczyścić stan błędu i spróbować jeszcze raz coś takiego prawdopodobnie pracować i po prostu ignorować złe numery:

#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

Alternatywnie, wywołaj wywołanie std :: cin.clear(), aby usunąć stan błędu przed następnym przejściem pętli. – hark

3

Biorąc pod uwagę, że komputer jest 32-bitowy, 10000000000 jest zbyt dużą liczbą, aby można ją było reprezentować przez int. Również konwertowanie int na char daje tylko od 0..255 lub -128..127 w zależności od kompilatora.

+0

To 0,221 lub -128,127. :) – unwind

0

Jednym z problemów jest to, że char ma rozmiar jednego bajtu, a więc może należy trzymać tylko cyfry od -127 do 128. Z drugiej strony, int ma zwykle 4 bajty i może przyjmować znacznie większe wartości. Drugi problem polega na tym, że wprowadzasz wartość, która jest zbyt duża, nawet dla int.

+0

przede wszystkim drukowanie "jakiegoś dziwnego znaku" nie jest przyczyną, po drugie znak nie jest domyślnie podpisany, jest to zależne od kompilatora. Jest * często * podpisany, ale nie musi być. –

5

Tak, Evan Teran zwrócił uwagę na większość rzeczy. Jedna rzecz, którą chcę dodać (skoro nie mogę skomentować jego komentarza :)) jest to, że musisz wykonać połączenie do istream :: clear przed wywołanie istream :: ignore. Powodem jest to, że istream :: ignore podobnie po prostu odmówi zrobienia czegokolwiek, jeśli strumień nadal znajduje się w stanie awarii.

+0

Dzięki, poprawione. Dostajesz uprowadzenie do tego;) –