!!!Chapter 6 Statement

6.1 Simple Statements

1. Expression statement:

An expression becomes an expression statement by following it with a semicolon. Expression statements cause the expression to be evaluated. Most commonly, expression statements contain expressions that when evaluated affect the program's state: assignment, increment, input, output:

ival + 5;    //expression statement

2. Null statement

null statement contains only one semicolon. It is useful when the language requires a statement but the program's logic does not (when loop work can be done in the condition):

//read until we hit EOF or find input sought
while (cin >> s && s != sought)
;           //null statement

We should always comment a null statement to clarify our intention.

6.3 Compound Statements (Blocks)

A compound statement, usually referred to as block, is a sequence of statements surrounded by a pair of curly braces. A block is a scope, names (variables) introduced inside the block is only accessible within the block or from blocks nested inside the block.

A block is not terminated by a semicolon. We can also define an empty block (like null statement).

6.4 Statement Scope

Some statements permit variable definitions within their control structure. A name introduced in a control structure is local to the statement and the scopes nested inside the statement. If the program needs to access the value of a variable used in control statement, then that variable must be defined outside the control structure:

int index = 0;
for (/* empty */; index !=a; ++index)      
if (index != b)      //ok, index is not defined inside for loop

The advantage is names of variables, which defined inside a control statement, can be reused afterwards.

6.5 The if Statement

An if statement conditionally executes another statement based on whether a specified expression is true.

1. Plain if:

The syntactic of plain if is:

if (condition)
   statement

The condition can be an expression or an initialized declaration:

if (a + b > c);                    //expression as condition
if (int ival = compute_value());   //initialization as condition

When a condition defines a variable, the variable must be initialized. And the initialized value is converted to bool, which means we can initialize arithmetic variable, IO types. But we cannot initialize string or vector inside condition.(Vector, string cannot be converted to bool)

2. if - else statement:

The syntactic of if else statement is:

if (condition)
   statement1
else
   statement2

statement2 can be any statement or block. It can be another if statement:

if (...)
   statement
else if(...)
   statement

Dangling-else problem: occurs when a statement contains more if clauses than else clauses. By default, else will match the closest if. But we can force an else to match an outer if by enclosing the inner if in a compound statement:

if (a <=b)
   if (a < b)
   statement1
else                   //else will match the inner if
   statement2
if (a <=b)
{
   if (a < b)
   statement1
}
else                   //else will match the outer if
   statement2

6.6 The switch Statement

A switch statement provides a more convenient way to write deeply nested if/else logic. switch sample:

//if ch is 'a' and we don't have break in each case, 
//it will execute both statement1 and statement2
switch (ch)
{
  case 'a':     //if ch is 'a', it will only execute statement1
    statement1;
    break;
  case 'b':
    statement2;
    break;
}

switch will first evaluate the parenthesized expression following switch. The expression must yield an integral result. The result of the expression is compared with the value associated with each case.

If 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.

Only a single value can be associated with a case label. So we may want to remove break to indicate an range:

//increase number if ch is a or b
switch (ch)
{
  case 'a':  
  case 'b': 
    ++Number;
    break;
}

Case labels need not appear on a new line, we can emphasize that the cases represent a range of values by listing them in a single line:

switch (ch)
{
  case 'a': case 'b':  case 'c':
    ++Number;
    break;
}

The default label provides the equivalent of an else clause:

switch (ch)
{
  case 'a': 
     ++aCnt;
     break;
  default:        //if ch is not 'a', increase otherCnt
     ++otherCnt;
     break;
}

A label may not stand alone; it must precede a statement. If a switch ends with the default case in which there is no work to be done, then the default label must be followed by a null statement. (Or break)

We can initialize a variable in the switch expression. The variable exists throughout the entire switch but not outside it:

switch (int ival = get_response())

Case labels must be constant integral expressions, it is also an error for any two case labels to have the same value:

//illegal case label values
case 3.14:          //noninteger
case ival;          //nonconstant

Variable definition inside a switch:

1. We could not define a variable in a place that might allow execution to bypass its definition:

case true;
    int i;           //error, i may be used by other cases, where it is not defined
    break
case false:
    ...

2. We can define the variable inside a block when needed:

case true;
{
    int i;           //ok, i only exist inside the block
}
    break
case false:
    ...

6.7 The while Statement

The while statement repeatedly executes a target statement as long as the condition is true. Here is the syntactic:

while (condition)
    statement

If the first evaluation of condition yields false, statement is not executed.

The condition can be an expression or an initialized variable definition:

while (!test)            //expression as condition
    statement

while (int i = search()) //initialized variable as condition
    statement

Variable defined in the condition are created and destroyed on each trip through the loop.

6.8 The for Loop Statement

The syntactic of a for statement:

for (initializer; condition; expression)
      statement

If the first evaluation of condition evaluates to false, statement is not executed.

If condition evaluates to false on the first iteration, expression is never executed.

The order of evaluation in a for loop:

1. initialization

2. condition is evaluated. If true, then for body is executed. If false, the loop terminates

3. execute the for body

4. expression is evaluated

After the first loop, it will continue as: 2,3,4,2,3,4...

As others, the variable defined inside the for loop is not accessible outside it.

A for header can omit any(or all) of initializer, condition, or expression. But the semicolon is still needed(it is used to represent a null statement.)

If we omit the condition, then it is equivalent to having written true in this part.(the loop will keep running). So we need breakor return in the statement.

Multiple objects may be defined in the init-statement; however, only one statement may appear. So all the objects must be of the same general type.

6.9 The do while Statement

The do while statement guarantees that its body is always executed at least once. The syntactic is:

do 
statement
while (condition);

Unlike while statement, the do while statement alwaysends with a semicolon.
The condition cannot be empty. Any variable referenced inside the condition must exist before the do statement itself.

Because the condition is not evaluated until after the statement or block is executed, so do-while statement does not allow variable definitions in the condition part:

//error: declaration statement within do condition is not supported
do {
    //...
    mumble(foo);
} while (int foo = get_foo());

6.10 The break Statement

A break statement terminates the nearest enclosing while, do while, for, switch statement. It will stop the loop/switch and continue the following statements.

A break can appear only within a loop or switch statement or in a statement nested inside a loop or switch (if statement).

6.11 The continue Statement

Th continue statement causes the current iteration of the nearest enclosing loop to terminate. Execution resumes with the evaluation of the condition in the case of a while or do while statement. In a for loop, execution continues by evaluating the expression inside the for header.

A continue can appear only inside a for, while, do while loop, including the blocks inside these loops.

6.12 The goto Statement

A goto statement provides an unconditional jump from the goto to a labeled statement in the same function.

The syntactic form is:

goto label;
...                 //will not execute this part
label: 
...

A label statement is any statement that i preceded by an identifier followed by a colon.

Use of goto is discouraged.

6.13 try Blocks and Exception Handling

Exceptions are run-time anomalies, such as out of memory or encountering unexpected input.

Exceptions support communication between the error-detecting and error-handling parts of a program. In C++ exception handling involves:

1. throw expressions

2. try blocks

3. A set of exception classes defined by the library.

6.13.1 A throw Expression

An exception is thrown using a throw expression, which consists of the keywordthrow followed by an expression. A throw expression is usually followed by a semicolon, making it into an expression statement. The type of the expression determines what kind of exception is thrown.

if (a != b)
throw runtime_error("Date does not match");

runtime_error type is one of the standard library exception types and is defined in the stdexcept header.

6.13.2 The try block

The general form of a try block:

try 
  {
      program-statements
  }
  catch (exception-specifier)
  {
      handler-statements
  }
  catch (exception-specifier)
  {
      handler-statements
  }
//...

A try block begins with the keyword try followed by a block, which as usual is a sequence of statements enclosed in braces. Following this block is a list of one or more catch clauses.

A catch clause consists of three parts : the keywordcatch, the declaration of a single type or single object within parentheses (referred to as exception specifier), and a block.

If the catch clause is selected to handle an exception, the associated block is executed. Once the catch clause finishes, execution continues with the statement immediately following the last catch clause of the try block.

The program-statements inside the try constitute the normal logic of the program. They can contain any C++ statements, including declaration. But variable declared here cannot be accessed outside the block.They are not accessible by the catch clauses. 

Functions are exited during the search for a handler, the search for a handler reverses the call chain.

6.13.3 Standard Exceptions

C++ library exception classes are defined in four headers:

1. the exception header

It defines most general kind of exception class named exception. It communicates only that exception occurs but provides no detail

2. the stdexcept header

It defines several general purpose exception classes. P 220

3. the new header

It defines the bad_alloc exception type, which is the exception thrown by new if it cannot allocate memory

4. the type_info header P 772

We can create, copy, and assign objects of any of the exception types. The exception, bad_alloc, and bad_cast (from type_info header) types define only a default constructor; it is not possible to provide an initializer for objects of these types.

The other exception types (mainly from stdexcept header) define only a single constructor that takes a string initializer, which is used to provide additional information about the error that occurred.

The exception types define only a single operation named what. That function takes no argument and returns a const char*.

E.G. P 217 & P 218

6.14 Using the Preprocessor for Debugging 

The program will contain debugging code that is executed only while the program is being developed. When the application is completed and ready to ship, the debugging code is turned off.

We use NDEBUG preprocessor variable to write conditional debugging code:

int main()
{
#ifndef NDEGUG
cerr << "starting main" << endl;
#endif
//....

if NDEBUG is not defined, then the statement between #ifndef and #endifwill be executed. Otherwise, the statement will not be executed.

By default, NDEBUG is not defined, so the code inside will be processed. So in the program development stage, we keep NDEBUGundefined. And we will defineNDEBUG preprocessor variable when ship the software.

The preprocessor defines four other constants that can be useful in debugging:

_ _FILE_ _name of the file.

_ _LINE_ _current line number

_ _TIME_ _time the file was compiled

_ _DATE_ _date the file was compiled

E.G. P 221

The assert Preprocessor Macro

We can also use NDEBUG preprocessor variable and theassert preprocessor macro to debug. The assert macro is defined in the cassert header.

Macros are handled by the preprocessor. Typically a macro contains a body of C++ code. The preprocessor inserts that code wherever we use the name of the macro.

Macro names must be unique within the program.

Because the preprocessor, not the compiler, handles prepprocessor names, those names are not defined within normal C++ scope. So we use assertdirectly.

The preprocessor macro takes one expression. It executes when NDEBUG is not defined.It will writes a message and terminate the program when the condition is false and do nothing when the condition is true:

assert(expr)
//example
assert (word.size() > threshold);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值