#include <iostream> using namespace std; int main() { string s; int i; i = 0; while (1) { i++; cin >> s; if (cin.fail()) return 0; cout << "String " << i << ": " << s << endl; } } |
You'll note, when you run this, it ends when the end of the file has been reached, because cin.fail() returns true here:
UNIX> g++ cinfail.cpp UNIX> cat input-1.txt Cats foot iron claw Neuro-surgeons scream for more At paranoias poison door. 21st century schizoid man. UNIX> a.out < input-1.txt String 1: Cats String 2: foot String 3: iron String 4: claw String 5: Neuro-surgeons String 6: scream String 7: for String 8: more String 9: At String 10: paranoias String 11: poison String 12: door. String 13: 21st String 14: century String 15: schizoid String 16: man. UNIX>cin.fail() also returns 1 if you try to read an integer and it receives something that cannot be converted to an integer. For example, see cinfail2.cpp:
#include <iostream> using namespace std; int main() { int j; int i; i = 0; while (1) { i++; cin >> j; if (cin.fail()) return 0; cout << "Integer " << i << ": " << j << endl; } } |
When we run it on input-2.txt, you see that it quits after reading the seventh word, because that is not an integer:
UNIX> g++ cinfail2.cpp UNIX> cat input-2.txt 30 40 50 60 70 -100 Fred 99 88 77 66 UNIX> a.out < input-2.txt Integer 1: 30 Integer 2: 40 Integer 3: 50 Integer 4: 60 Integer 5: 70 Integer 6: -100 UNIX>So, how do you know if you read an incorrect input word, or if you are at the end of the file? This is when you use cin.eof() and cin.clear(). First, cin.eof() returns 1 if you tried to read something but were at the end of file. Second, cin.clear() is used to "clear the error state" of cin. In other words, when an input failure occurs and cin.fail() returns true, the input buffer (cin) is placed in an "error state", and further input processing will not work unless you clear the state by calling cin.clear(). Used together with cin.fail(), cin.eof() and cin.clear() let you process and error check a variety of input. For example, cinfail3.cpp below reads all the integers in a file and prints them out. It uses cin.fail()/cin.clear() to check for and ignore non-integers, and uses cin.eof() to discover the end of the file:
#include <iostream> using namespace std; int main() { int j; int i; string dummy; i = 0; while (1) { cin >> j; if (!cin.fail()) { i++; cout << "Integer " << i << ": " << j << endl; } else if (cin.eof()) { return 0; } else { cin.clear(); cin >> dummy; } } } |
When we run it on input-3.txt, you see that it works as promised:
UNIX> g++ cinfail3.cpp UNIX> cat input-3.txt Black 100 as 50 a 25 dark 12 night -5 she 0 was -500 UNIX> a.out < input-3.txt Integer 1: 100 Integer 2: 50 Integer 3: 25 Integer 4: 12 Integer 5: -5 Integer 6: 0 Integer 7: -500 UNIX>
if (strchr("0Ab.:/", c) != NULL)If that returns true, then c is one of the desired characters. Otherwise, it's not.
For example, suppose we want to write a program that has the user enter a card by typing the rank and the suit, like "AH" for the ace of hearts, and "2C" for the two of clubs. Here's a way to do it (in readcard.cpp):
#include <iostream> #include <cstring> using namespace std; const char *ranks = "23456789TJQKA"; const char *suits = "CDHS"; const char *longranks[13] = { "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace" }; const char *longsuits[4] = { "Clubs", "Diamonds", "Hearts", "Spades" }; int main() { string s; const char *str; int cnum; while (1) { cout << "Enter a card: "; cin >> s; str = s.c_str(); if (strlen(str) != 2) { cout << "The card must the format 'rank-suit', such as 'AH' or '2C'\n"; } else if (strchr(ranks, str[0]) == NULL) { cout << "The rank must be one of " << ranks << endl; } else if (strchr(suits, str[1]) == NULL) { cout << "The suit must be one of " << suits << endl; } else { cnum = (strchr(suits, str[1]) - suits)*13 + (strchr(ranks, str[0]) - ranks); cout << "Good card: #" << cnum << ": The " << longranks[cnum%13] << " of " << longsuits[cnum/13] << ".\n"; } } } |
Note the use of pointer arithmetic to get the rank and suit. Study that one carefully. It's a good trick to know.
Here's an example of it running:
UNIX> g++ readcard.cpp UNIX> a.out Enter a card: AH Good card: #38: The Ace of Hearts. Enter a card: 2C Good card: #0: The Two of Clubs. Enter a card: 7S Good card: #44: The Seven of Spades. Enter a card: TD Good card: #21: The Ten of Diamonds. Enter a card: YS The rank must be one of 23456789TJQKA Enter a card: TY The suit must be one of CDHS Enter a card: Fred The card must the format 'rank-suit', such as 'AH' or '2C' Enter a card: ^C UNIX>