5-Statements

Please indicate the source: http://blog.csdn.net/gaoxiangnumber1

Welcome to my github: https://github.com/gaoxiangnumber1

5.1. Simple Statements

  • Most statements in C++ end with a semicolon. An expression, such as ival + 5, becomes an expression statement when it is followed by a semicolon. Expression statements cause the expression to be evaluated and its result discarded:
ival + 5;  // useless expression statement: addition is done but the result is not used.

Null Statements

  • The empty statement known as a null statement(a single semicolon).
    ; // null statement

Compound Statements (Blocks)

  • A compound statement, referred to as a block, is a(possibly empty) sequence of statements and declarations surrounded by a pair of curly braces. A block is a scope (§2.2.4, p. 48). Names introduced inside a block are accessible only in that block and in blocks nested inside that block. Names are visible from where they are defined until the end of the immediately enclosing block.
  • We can define an empty block by writing a pair of curlies with no statements. An empty block is equivalent to a null statement:
while (cin >> s && s != sought)
{ } // empty block

Exercises Section 5.1

Exercise 5.1

What is a null statement? When might you use a null statement?

  • ;

Exercise 5.2

What is a block? When might you might use a block?

  • A compound statement, referred to as a block, is a(possibly empty) sequence of statements and declarations surrounded by a pair of curly braces.

Exercise 5.3

Use the comma operator(§ 4.10, p. 157) to rewrite the while loop from §1.4.1 (p. 11) so that it no longer requires a block. Explain whether this rewrite improves or diminishes the readability of this code.

  • diminishes the readability of this code

5.2. Statement Scope

  • We can define variables inside the control structure of the if, switch, while, and for statements. Variables defined in the control structure are visible only within that statement and are out of scope after the statement ends. If we need access to the control variable, then that variable must be defined outside the statement.

Exercises Section 5.2

Exercise 5.4

Explain each of the following examples, and correct any problems you detect.
(a) while(string::iterator iter != s.end()) { /* … */ }
(b) while (bool status = find(word)) { /* … */ }
if (!status) { /* … */ }

  • Not initialized.
  • status is out of scope.

5.3. Conditional Statements

  • The if statement determines the flow of control based on a condition.
  • The switch statement evaluates an integral expression and chooses one of several execution paths based on the expression’s value.

5.3.1. The if Statement

  • if conditionally executes another statement based on whether a specified condition is true. Two forms of if: one with an else branch and one without.
if (condition)
    statement
if (condition)
    statement
else
    statement2
  • condition must be enclosed in parentheses. condition can be an expression or an initialized variable declaration(§ 5.2, p. 174). The expression or variable must have a type that is convertible(§ 4.11, p. 159) to bool. Either or both statement and statement2 can be a block.

Watch Your Braces

  • It is a common mistake to forget the curly braces when multiple statements must be executed as a block

Dangling else

  • How do we know to which if a given else belongs?
    This problem referred as a dangling else. Each else is matched with the closest preceding unmatched if.

Exercises Section 5.3.1

Exercise 5.5

Using an if-else statement, write your own version of the program to generate the letter grade from a numeric grade.

#include <iostream>
#include <vector>
#include <string>

using std::cin;
using std::cout;
using std::vector;
using std::string;

int main()
{
    vector<string> scores = {"F", "D", "C", "B", "A", "A++"};
    for(int grade = 0; cin >> grade;)
    {
        string letter;
        if(grade < 60)
        {
            letter = scores[0];
        }
        else
        {
            letter = scores[(grade - 50) / 10];
            if(grade != 100)
            {
                letter += (grade % 10 > 7 ? "+" : (grade % 10 < 3 ? "-" : ""));
            }
        }
        cout << letter << '\n';
    }

    return 0;
}

Exercise 5.6

Rewrite your grading program to use the conditional operator(§ 4.7, p. 151) in place of the if-else statement.

#include <iostream>
#include <vector>
#include <string>

using std::cin;
using std::cout;
using std::vector;
using std::string;

int main()
{
    vector<string> scores = {"F", "D", "C", "B", "A", "A++"};
    int grade = 0;
    while(cin >> grade)
    {
        string lettergrade = grade < 60 ? scores[0] : scores[(grade - 50) / 10];
        lettergrade +=
            (grade == 100 || grade < 60)
            ? ""
            : (grade % 10 > 7) ? "+" : (grade % 10 < 3) ? "-" : "";
        cout << lettergrade << '\n';
    }

    return 0;
}

Exercise 5.7

Correct the errors in each of the following code fragments:
(a)
if (ival1 != ival2)
ival1 = ival2
else ival1 = ival2 = 0;
(b)
if (ival < minval)
minval = ival;
occurs = 1;
(c)
if (int ival = get_value())
cout << “ival = ” << ival << endl;
if (!ival)
cout << “ival = 0\n”;
(d)
if (ival = 0)
ival = get_value();

  • ival1 = ival2;
  • Add braces
  • out of scope
  • if(ival == 0)

Exercise 5.8

What is “dangling else”? How are clauses resolved in C++?

  • dangling else: how do we know to which if a given else belongs?
  • Each else is matched with the closest preceding unmatched if.

5.3.2. The switch Statement

  • A switch statement executes by evaluating the parenthesized expression that follows the keyword switch. That expression may be an initialized variable declaration(§ 5.2, p. 174). The expression is converted to integral type. The result of the expression is compared with the value associated with each case.
  • If the expression matches the value of a case label, execution begins with the first statement following that label. Execution continues normally from that statement through the end of the switch or until a break statement.
  • If no match is found, execution falls through to the first statement following the switch.
  • The case keyword and its associated value together are known as the case label. case labels must be integral constant expressions. It is an error for any two case labels to have the same value.
int num1, num2 = 0;
const int num3 = 0;
while(cin >> num1)
{
    switch(num1)
    {
    case 3.14:  // Equivalent to "case 3:"
        cout << "case 3.14:\n";
        break;
    case 3:     // error: duplicate case value
    case num2:  // error: the value of ‘num2’ is not usable in a constant expression
    case num3:
        cout << "case num3(0):\n";
        break;
    default:
        cout << "No match\n";
    }
}

Control Flow within a switch

  • After a case label is matched, execution starts at that label and continues across all the remaining cases or until the program explicitly interrupts it. To avoid executing code for subsequent cases, we must use break to tell the compiler to stop execution.
  • Each case label can have only a single value, but sometimes we have two or more values that share a common set of actions. In such instances, we omit a break statement, allowing the program to fall through multiple case labels.

The default Label

  • The statements following the default label are executed when no case label matches the value of the switch expression.

Variable Definitions inside the Body of a switch

  • When execution jumps to a particular case, any code that occurred inside the switch before that label is ignored. What happens if the code that is skipped includes a variable definition?
  • Answer: It is illegal to jump from a place where a variable with an initializer is out of scope to a place where that variable is in scope.

Exercises Section 5.3.2

Exercise 5.9

Write a program using a series of if statements to count the number of vowels in text read from cin.

#include <iostream>

using std::cin;
using std::cout;

int main()
{
    int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while(cin >> ch)
    {
        if (ch == 'a')
        {
            ++aCnt;
        }
        else if (ch == 'e')
        {
            ++eCnt;
        }
        else if (ch == 'i')
        {
            ++iCnt;
        }
        else if (ch == 'o')
        {
            ++oCnt;
        }
        else if (ch == 'u')
        {
            ++uCnt;
        }
    }
    cout << "Number of vowel a: \t" << aCnt << '\n'
         << "Number of vowel e: \t" << eCnt << '\n'
         << "Number of vowel i: \t" << iCnt << '\n'
         << "Number of vowel o: \t" << oCnt << '\n'
         << "Number of vowel u: \t" << uCnt << '\n';

    return 0;
}

Exercise 5.10

There is one problem with our vowel-counting program as we’ve implemented it: It doesn’t count capital letters as vowels. Write a program that counts both lower- and uppercase letters as the appropriate vowel—that is, your program should count both ‘a’ and ‘A’ as part of aCnt, and so forth.

#include <iostream>

using std::cin;
using std::cout;

int main()
{
    int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while(cin >> ch)
    {
        switch (ch)
        {
        case 'a':
        case 'A':
            ++aCnt;
            break;
        case 'e':
        case 'E':
            ++eCnt;
            break;
        case 'i':
        case 'I':
            ++iCnt;
            break;
        case 'o':
        case 'O':
            ++oCnt;
            break;
        case 'u':
        case 'U':
            ++uCnt;
            break;
        }
    }
    cout << "Number of vowel a(A): \t" << aCnt << '\n'
         << "Number of vowel e(E): \t" << eCnt << '\n'
         << "Number of vowel i(I): \t" << iCnt << '\n'
         << "Number of vowel o(O): \t" << oCnt << '\n'
         << "Number of vowel u(U): \t" << uCnt << '\n';

    return 0;
}

Exercise 5.11

Modify our vowel-counting program so that it also counts the number of blank spaces, tabs, and newlines read.

#include <iostream>

using std::cin;
using std::cout;

int main()
{
    int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    int spaceCnt = 0, tabCnt = 0, newlineCnt = 0;
    char ch;
    while(cin >> std::noskipws >> ch)
    {
        switch (ch)
        {
        case 'a':
        case 'A':
            ++aCnt;
            break;
        case 'e':
        case 'E':
            ++eCnt;
            break;
        case 'i':
        case 'I':
            ++iCnt;
            break;
        case 'o':
        case 'O':
            ++oCnt;
            break;
        case 'u':
        case 'U':
            ++uCnt;
            break;
        case ' ':
            ++spaceCnt;
            break;
        case '\t':
            ++tabCnt;
            break;
        case '\n':
            ++newlineCnt;
            break;
        }
    }
    cout << "Number of vowel a(A): \t" << aCnt << '\n'
         << "Number of vowel e(E): \t" << eCnt << '\n'
         << "Number of vowel i(I): \t" << iCnt << '\n'
         << "Number of vowel o(O): \t" << oCnt << '\n'
         << "Number of vowel u(U): \t" << uCnt << '\n'
         << "Number of space: \t" << spaceCnt << '\n'
         << "Number of tab char: \t" << tabCnt << '\n'
         << "Number of new line: \t" << newlineCnt << '\n';

    return 0;
}

Exercise 5.12

Modify our vowel-counting program so that it counts the number of occurrences of the following two-character sequences: ff, fl, and fi.

#include <iostream>

using std::cin;
using std::cout;

int main()
{
    int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    int spaceCnt = 0, tabCnt = 0, newlineCnt = 0, ffCnt = 0, flCnt = 0, fiCnt = 0;
    char ch, prech = '\0';
    while (cin >> std::noskipws >> ch)
    {
        switch (ch)
        {
        case 'a':
        case 'A':
            ++aCnt;
            break;
        case 'e':
        case 'E':
            ++eCnt;
            break;
        case 'i':
            if (prech == 'f')
            {
                ++fiCnt;
            }
        case 'I':
            ++iCnt;
            break;
        case 'o':
        case 'O':
            ++oCnt;
            break;
        case 'u':
        case 'U':
            ++uCnt;
            break;
        case ' ':
            ++spaceCnt;
            break;
        case '\t':
            ++tabCnt;
            break;
        case '\n':
            ++newlineCnt;
            break;
        case 'f':
            if (prech == 'f')
            {
                ++ffCnt;
            }
            break;
        case 'l':
            if (prech == 'f')
            {
                ++flCnt;
            }
            break;
        }
        prech = ch;
    }

    cout << "Number of vowel a(A): \t" << aCnt << '\n'
         << "Number of vowel e(E): \t" << eCnt << '\n'
         << "Number of vowel i(I): \t" << iCnt << '\n'
         << "Number of vowel o(O): \t" << oCnt << '\n'
         << "Number of vowel u(U): \t" << uCnt << '\n'
         << "Number of space: \t" << spaceCnt << '\n'
         << "Number of tab char: \t" << tabCnt << '\n'
         << "Number of new line: \t" << newlineCnt << '\n'
         << "Number of ff: \t" << ffCnt << '\n'
         << "Number of fl: \t" << flCnt << '\n'
         << "Number of fi: \t" << fiCnt << '\n';

    return 0;
}

Exercise 5.13

Each of the programs in the highlighted text on page 184 contains a common programming error. Identify and correct each error.

// b:
unsigned index = some_value();
switch (index)
{
case 1:
    int ix = get_value();
    ivec[ ix ] = index;
    break;
default:
    ix = ivec.size()-1;
    ivec[ ix ] = index;
}
//c
unsigned evenCnt = 0, oddCnt = 0;
int digit = get_num() % 10;
switch (digit)
{
case 1, 3, 5, 7, 9:
    oddcnt++;
    break;
case 2, 4, 6, 8, 10:
    evencnt++;
    break;
}
  • Omit “break;”
  • ix is out of scope
  • case labels should be one number only.
  • case labels must be constants expressions.

5.4. Iterative Statements

  • Iterative statements(loops) provide for repeated execution until a condition is true. while and for test the condition before executing the body. do while executes the body and then tests its condition.

5.4.1. The while Statement

while (condition)
    statement
  • The condition can be an expression or an initialized variable declaration(§5.2, p.174). If the first evaluation of condition yields false, statement is not executed.

Exercises Section 5.4.1

Exercise 5.14

Write a program to read strings from standard input looking for duplicated words. The program should find places in the input where one word is followed immediately by itself. Keep track of the largest number of times a single repetition occurs and which word is repeated. Print the maximum number of duplicates, or else print a message saying that no word was repeated. For example, if the input is
how now now now brown cow cow
the output should indicate that the word now occurred three times.

#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::string;

int main()
{
    string pre_word = "", word = "", max_repeat_word = "";
    int repeat_times = 0, max_repeat_times = 0;

    while (cin >> word)
    {
        if (word == pre_word)
        {
            ++repeat_times;
        }
        else
        {
            repeat_times = 1;
            pre_word = word;
        }

        if (max_repeat_times < repeat_times)
        {
            max_repeat_times = repeat_times;
            max_repeat_word = pre_word;
        }
    }

    if (max_repeat_times <= 1)
    {
        cout << "no word was repeated" << '\n';
    }
    else
    {
        cout << "the word '" << max_repeat_word << "' occurred " << max_repeat_times << " times" << '\n';
    }
}

5.4.2. Traditional for Statement

for(init-statement; condition; expression)
    statement
  • init-statement must be a declaration statement, an expression statement, or a null statement.
  • condition serves as the loop control. If the first evaluation of condition yields false, statement is not executed.
  • expression is evaluated after each iteration of the loop.

Execution Flow in a Traditional for Loop

  1. init-statement is executed once at the start of the loop.
  2. condition is evaluated. If the condition is false on the first iteration, then the for body is not executed at all.
  3. If the condition is true, the for body executes.
  4. Finally, expression is evaluated.
    • Step 1 is executed only once on entry to the loop. Steps 2, 3, and 4 are repeated until the condition evaluates as false.

Multiple Definitions in the for Header

  • init-statement can define several objects, but all objects must have the same base type(§ 2.3, p. 50).

Omitting Parts of the for Header

  • Omitting condition is equivalent to writing true as the condition.

Exercises Section 5.4.2

Exercise 5.15

Explain each of the following loops. Correct any problems you detect.

(a)
for(int ix = 0; ix != sz; ++ix) { /* . . . */ }
if(ix != sz)
    // . . .
(b)
int ix;
for(ix != sz; ++ix) { /* . . . */ }
(c)
for (int ix = 0; ix != sz; ++ix, ++ sz) { /* . . . */ }
  • ix is out of scope
  • omit init-statement of for(;;)
  • infinity loop

Exercise 5.16

The while loop is particularly good at executing while some condition holds; for example, when we need to read values until end-of-file. The for loop is generally thought of as a step loop: An index steps through a range of values in a collection. Write an idiomatic use of each loop and then rewrite each using the other loop construct. If you could use only one loop, which would you choose? Why?

// while idiomatic 
int i; 
while ( cin >> i )
    // ... 
// same as for 
for (int i = 0; cin >> i;)
    // ... 
// for idiomatic 
for (int i = 0; i != size; ++i)
    // ... 
// same as while 
int i = 0; 
while (i != size)
{
    // ...
    ++i; 
}

Exercise 5.17

Given two vectors of ints, write a program to determine whether one vector is a prefix of the other. For vectors of unequal length, compare the number of elements of the smaller vector. For example, given the vectors containing 0, 1, 1, and 2 and 0, 1, 1, 2, 3, 5, 8, respectively your program should return true.

#include <iostream>
#include <vector>

using std::cout;
using std::vector;

bool IsPrefix(vector<int> &lhs, vector<int> &rhs)
{
    if(lhs.size() > rhs.size())
    {
        return IsPrefix(rhs, lhs);
    }
    for(int index = 0; index != lhs.size(); ++index)
    {
        if(lhs[index] != rhs[index])
        {
            return false;
        }
    }
    return true;
}

int main()
{
    vector<int> vec1 = { 0, 1, 1, 2 };
    vector<int> vec2 = { 0, 1, 1, 2, 3, 5, 8 };
    cout << (IsPrefix(vec1, vec2) ? "Yes\n" : "No\n");

    return 0;
}

5.4.3. Range for Statement(C++11)

for(declaration : expression)
    statement
  • declaration defines a variable. It must be possible to convert each element of the sequence to the variable’s type. The easiest way is using auto(§ 2.5.2, p. 68). If we want to write to the elements in the sequence, the loop variable must be a reference type.
  • expression must represent a sequence.
  • On each iteration, the control variable is defined and initialized by the next value in the sequence after statement is executed.
  • We cannot use a range for to add elements to a vector(or other container): In a range for, the value of vec.end() is cached. If we add elements to(or remove them from) the sequence, the value of end might be invalidated(§ 3.4.1, p. 110).

5.4.4. The do while Statement

do
{
    statement
}
while(condition);
  • statement is executed before condition is evaluated.
  • condition cannot be empty. Variables used in condition must be defined outside the body of the do while statement.
  • do while ends with a semicolon after the parenthesized condition.
  • Because the condition is not evaluated until after the statement is executed, the do while loop does not allow variable definitions inside the condition.
do
{
    int num1 = 0;
    cout << "AAAAAA\n";
}
while(num1);        // error: ‘num1’was not declared in this scope

do
{
    cout << num2;   // error: ‘num2’ was not declared in this scope
}
while(int num2 = 0);

Exercises Section 5.4.4

Exercise 5.18

Explain each of the following loops. Correct any problems you detect.

(a)
do
{
    int v1, v2;
    cout << "Please enter two numbers to sum:" ;
    if(cin >> v1 >> v2)
    {
        cout << "Sum is: " << v1 + v2 << endl;
    }
}
while(cin);
(b)
do
{
    // . . .
}
while (int ival = get_response());
(c)
do
{
    int ival = get_response();
}
while (ival);
  • Right
  • int ival; before do{}while();
  • ival is out of scope.

Exercise 5.19

Write a program that uses a do while loop to repetitively request two strings from the user and report which string is less than the other.

#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::endl;
using std::string;

int main()
{
    string judge, str1, str2;
    do
    {
        cout << "Input two strings: ";
        cin >> str1 >> str2;
        cout << (str1 <= str2 ? str1 : str2) << " is small\n";
        cout << "Continue?(y/n): ";
        cin >> judge;
    }
    while(judge == "y");
    return 0;
}

5.5. Jump Statements

  • Four jumps: break, continue, goto and return.

5.5.1. The break Statement

  • A break statement terminates the nearest enclosing while, do while, for, or switch statement. Execution resumes at the statement immediately following the terminated statement.
  • A break can appear only within an iteration statement or switch statement(including inside statements or blocks nested inside such loops). A break affects only the nearest enclosing loop or switch:

Exercises Section 5.5.1

Exercise 5.20

Write a program to read a sequence of strings from the standard input until either the same word occurs twice in succession or all the words have been read. Use a while loop to read the text one word at a time. Use the break statement to terminate the loop if a word occurs twice in succession. Print the word if it occurs twice in succession, or else print a message saying that no word was repeated.

#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::endl;
using std::string;

int main()
{
    string read, tmp;
    while (cin >> read)
    {
        if (read == tmp)
        {
            break;
        }
        else
        {
            tmp = read;
        }
    }
    if (cin.eof())
    {
        cout << "no word was repeated." << endl;
    }
    else
    {
        cout << read << " occurs twice in succession." << endl;
    }
    return 0;
}

5.5.2. The continue Statement

  • A continue statement terminates the current iteration of the nearest enclosing loop and immediately begins the next iteration. A continue can appear only inside a for, while, or do while loop, including inside statements or blocks nested inside such loops.
  • A continue may appear inside a switch only if that switch is embedded inside an iterative statement.

Exercises Section 5.5.2

Exercise 5.21

Revise the program from the exercise in § 5.5.1 (p. 191) so that it looks only for duplicated words that start with an uppercase letter.

#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
    string curr, prev;
    bool no_twice = true;
    while (cin >> curr)
    {
        if(isupper(curr[0]) && prev == curr)
        {
            cout << curr << ": occurs twice in succession." << endl;
            no_twice = false;
            break;
        }
        prev = curr;
    }

    if (no_twice)
    {
        cout << "no word was repeated." << endl;
    }

    return 0;
}

5.5.3. The goto Statement

  • goto label;
    label is an identifier that identifies a statement. A labeled statement is any statement that is preceded by an identifier followed by a colon:
    end: return; // labeled statement; may be the target of a goto
  • Label identifiers are independent of names used for variables and other identifiers. The goto and the labeled statement to which it transfers control must be in the same function.
  • A goto cannot transfer control from a point where an initialized variable is out of scope to a point where that variable is in scope. Jump backward over an already executed definition is okay. Jumping back to a point before a variable is defined destroys the variable and constructs it again.

Exercises Section 5.5.3

Exercise 5.22

The last example in this section that jumped back to begin could be better written using a loop. Rewrite the code to eliminate the goto.

for(int sz = get_size(); sz <= 0; sz = get_size());

5.6. try Blocks and Exception Handling

  • Exceptions are run-time anomalies that exist outside the normal functioning of a program.
  • Exception handling is used when one part of a program detects a problem that it cannot resolve and the problem is such that the detecting part of the program cannot continue. In such cases, the detecting part signals what happened and stops processing.
  • A program that contains code that might raise an exception usually has another part to handle whatever happened.
  • Exception handling involves
    1. throw expressions: the detecting part uses it to indicate that it encountered something it can’t handle. A throw raises an exception.
    2. try blocks: the handling part uses it to deal with an exception. A try block starts with the keyword try and ends with one or more catch clauses. Exceptions thrown from code executed inside a try block are handled by one of the catch clauses that are also known as exception handlers.
    3. A set of exception classes that are used to pass information about what happened between a throw and an associated catch.

5.6.1. A throw Expression

  • We use a throw expression to raise an exception. A throw consists of the keyword throw followed by an expression. The type of the expression determines what kind of exception is thrown. A throw expression is followed by a semicolon.
#include <iostream>
#include <stdexcept>

using std::cout;
using std::runtime_error;

int main()
{
    int num1 = 0;
    if(num1 == 0)
    {
        throw runtime_error("ZERO");
    }
}
terminate called after throwing an instance of 'std::runtime_error'
  what():  ZERO
Aborted
  • We throw an expression that is an object of type runtime_error. Throwing an exception terminates the current function and transfers control to a handler that will know how to handle this error.
  • The type runtime_error is one of the standard library exception types and is defined in . We must initialize a runtime_error by giving it a string or a C-style character string(§ 3.5.4, p. 122). That string provides additional information about the problem.

5.6.2. The try Block

try
{
    program-statements
}
catch (exception-declaration)
{
    handler-statements
}
catch (exception-declaration)
{
    handler-statements
}
// . . .
  • A try block begins with “try” followed by a block which is a sequence of statements enclosed in curly braces.
  • Following the try block is a list of one or more catch clauses. A catch consists of three parts: the keyword catch, the declaration of a(possibly unnamed) object within parentheses(referred to as an exception declaration), and a block. When a catch is selected to handle an exception, the associated block is executed. Once the catch finishes, execution continues with the statement immediately following the last catch clause of the try block.
  • The program-statements can contain any C++ statement. Variables declared inside a try block are inaccessible outside the block, in particular, they are not accessible to the catch clauses.

Writing a Handler

#include <iostream>
#include <stdexcept>

using std::cin;
using std::cout;
using std::runtime_error;

int main()
{
    int num1;
    while(cin >> num1)
    {
        try
        {
            if(num1 == 0)
            {
                throw runtime_error("Input Error: 0");
            }
            else
            {
                cout << "Continue\n";
            }
        }
        catch(runtime_error error)
        {
            cout << error.what() << "\nTry Again?(y/n): ";
            char ch;
            cin >> ch;
            if(!cin || ch == 'n')
            {
                break;
            }
        }
    }
}
  • Each of the library exception classes defines what() member function that takes no arguments and return a C-style character string(i.e., a const char*). The what member of runtime_error returns a copy of the string used to initialize the particular object.

Functions Are Exited during the Search for a Handler

  • The search for a handler reverses the call chain.
  • When an exception is thrown, the function that threw the exception is searched first. If no matching catch is found, that function terminates. The function that called the one that threw is searched next. If no handler is found, that function also exits. That function’s caller is searched next, and so on back up the execution path until a catch of an appropriate type is found. If no appropriate catch is found, execution is transferred to a library function named terminate whose behavior is system dependent but is guaranteed to stop further execution of the program.
  • Exceptions that occur in programs that do not define any try blocks are handled in the same manner: if there are no try blocks, there can be no handlers. If a program has no try blocks and an exception occurs, then terminate is called and the program is exited.
  • Programs that properly clean up during exception handling are said to be exception safe.

5.6.3. Standard Exceptions

  • C++ defines several classes that it uses to report problems encountered in the functions in the standard library. These exception classes are also intended to be used in the programs we write. These classes are defined in four headers:
    1. defines the most general kind of exception class named exception. It communicates only that an exception occurred but provides no additional information.
    2. defines several general-purpose exception classes(Table 5.1).
    3. defines the bad_alloc exception type(§ 12.1.2 (p. 458)).
    4. defines the bad_cast exception type(§ 19.2 (p. 825)).

  • We can create, copy, and assign objects of any of the exception types.
  • We can only default initialize(§ 2.2.1, p. 43) exception, bad_alloc, and bad_cast objects; it is not possible to provide an initializer for objects of these exception types.
  • We can initialize the other exception types from either a string or a C-style string, but cannot default initialize them, we must supply an initializer. That initializer is used to provide additional information about the error that occurred.
  • The exception types define only a single operation named what that takes no arguments and returns a const char* that points to a C-style character string. The purpose of this C-style character string is to provide some sort of textual description of the exception thrown.
  • The contents of the C-style string that what returns depends on the type of the exception object. For the types that take a string initializer, the what function returns that string. For the other types, the value of the string that what returns varies by compiler.

Exercises Section 5.6.3

Exercise 5.23

Write a program that reads two integers from the standard input and prints the result of dividing the first number by the second.

#include <iostream>

using std::cin;
using std::cout;

int main(void)
{
    int a, b;
    cin >> a >> b;
    cout << a / b;

    return 0;
}

Exercise 5.24

Revise your program to throw an exception if the second number is zero. Test your program with a zero input to see what happens on your system if you don’t catch an exception.

#include <iostream>
#include <stdexcept>

using std::cin;
using std::cout;
using std::runtime_error;

int main()
{
    int a, b;
    cin >> a >> b;
    if(b == 0)
    {
        throw runtime_error("Input Error: 0");
    }
    cout << a / b;

    return 0;
}

Exercise 5.25

Revise your program from the previous exercise to use a try block to catch the exception. The catch clause should print a message to the user and ask them to supply a new number and repeat the code inside the try.

#include <iostream>
#include <stdexcept>

using std::cin;
using std::cout;
using std::endl;
using std::runtime_error;

int main()
{
    int num1, num2;
    cout << "Input two integers: ";
    while(cin >> num1 >> num2)
    {
        try
        {
            if(num2 == 0)
            {
                throw runtime_error("Divisor is 0");
            }
            cout << num1 / num2 << endl;
            cout << "Input two integers: ";
        }
        catch (runtime_error error)
        {
            cout << error.what() << "\n" << "Try again.\nInput two integers: ";
        }
    }

    return 0;
}

Chapter Summary

Please indicate the source: http://blog.csdn.net/gaoxiangnumber1

Welcome to my github: https://github.com/gaoxiangnumber1

你可能感兴趣的:(github,C语言)