Home Previous Next

CSC240 :: Lecture Note :: Week 02
Assignments | Code | Handouts | Resources | Email Thurman {Twitter::@compufoo Facebook::CSzero}
{GDT::Bits:: Time  |  Weather  |  Populations  |  Special Dates}

Overview

Assignment(s): [last week] #Knuth (due 9/22/2017) ... [this week] #ArithOps (due 9/29/2017)

Handouts: [last week] HowToSubmitAssignments

Code: [last week] helloworld.c | HelloWorld.cpp | HelloWorld2.cpp | { preproc.cpp | preproc0.h | preproc1.h }
C++Template.txt | BadHelloWorld.cpp | LongStringLiteral.cpp

[this week] io.cpp | Limits.cpp | isspace.cpp | RandomInts.cpp | PrimitiveTypes.cpp | Constants.cpp | ArithOps.cpp | itofi.cpp |
Expressions0.cpp | Expressions1.cpp | Expressions2.cpp | Expressions3.cpp | RelationalOps.cpp | LogicalOps.cpp |
Age0.cpp | Age1.cpp | Age2.cpp | NewAge.cpp | ifcode.cpp | Adder.cpp | DoAdder.cpp | ForAdder.cpp


The C and C++ Compilation Process

C and C++ are high-level, 3rd-generation languages. These types of languages must be translated into a machine language in order to be executed by a CPU. The process of translating high-level language into machine language is called the compilation process.

The compilation process consists of the following steps.

   edit source code ->  compile   ->   link    ->   execute
      (editor)         (compiler)    (linker)       (loader)

Program source code is entered into a file using a text editor. After the code has been entered, a compiler program is started that translates the source into an object code file. The object code file is linked with other object code files that come with the compiler and an executable file (or program) is created. In order to execute the program, a program called the loader copies the executable file into the memory of the computer and sends an execute command to the CPU.

It should be noted that errors can occur during each step


source      +----------+      object     +--------+      executable
file   ---> | compiler | ---> file  ---> | linker | ---> file      ---+
(x.c)       +----------+      (x.o)      +--------+      (x)          |
                                             ^                        |
                                             |                        v
                                             |                    +--------+
                                             |                    | loader |
                                     Standard C Library           +--------+
                                     (stdc.lib                        |
                                          stdio.o                     |
                                          stdlib.o                    v
                                          math.o                     CPU
                                          ...)

A source file ending with ".c" contains C source code; whereas, a file ending with ".cpp" is a C++ file (note: ".C" suffix may also indicate a C++ source file). A file ending with ".h" can be both a C and C++ header file. Sometimes the suffix ".hpp" (or ".H") is used to indicate a C++ only header file.

The compiler is a program that usually consists of many phases. The first phase of compilation is called preprocessing. The preprocessor does many things, but two features that must be learned immediately are file inclusion and macro (manifest constant) definitions. After preprocessing, the compiler executes two primary steps: lexical analysis and parsing. During lexical analysis, the source code is broken up into tokens and the tokens are passed to the parser. The parser does syntax and semantic analysis, which includes the generation of object code (i.e. machine language).

The linker "combines" all object code files into an executable file (by default, named a.out on Unix systems). Typically, the object files created by your source files are linked with object files that are packaged into libraries.

Most implementations allow each step of the compilation process to be executed as a stand-alone procedure. For example, compile a source file but do not invoke the linker; execute the preprocessor only; or, invoke the linker only.

Some older compilers translate C source code into assembly language, then execute an assembler program to translate the assembly language into machine language.

Early C++ compilers (those prior to 1992) translated C++ code into C code and then executed the C compiler.

The loader reads a program (i.e. executable file) into memory. Once this is completed, it becomes a process and the CPU executes it.

{TopOfPage} {Resources}


Variables, Identifiers and Keywords

A variable is a location in the computer's memory where a value can be stored for use by a program.

An identifier is a name supplied to a variable. An identifier in C is a sequence of letters and digits. The first character must be a letter; the underscore _ counts as a letter. Upper and lower case letters are different (i.e. C is case sensitive). Good programming practice: avoid using leading underscores in identifiers. In addition, current convention is to start variable names with a lower case letter.

A keyword is a predefined identifier that has special meaning to the compiler and it is reserved by the language.

C Keywords

C reserves the following identifiers for use as keywords, they cannot be used otherwise.

   auto, break, case, char, const, continue, default, do, double,
   else, enum, extern, float, for, goto, if, int, long, register,
   return, short, signed, sizeof, static, struct, switch, typedef,
   union, unsigned, void, volatile, while
C9X indicates that bool will become a C keyword.
C++ Keywords

The following are potential C identifiers that are keywords in C++.

   and, and_eq, asm, bitand, bitor, bool, catch, class, compl, const_cast,
   delete, dynamic_cast, explicit, false, friend, inline, mutable,
   namespace, new, not, not_eq, operator, or, or_eq, private, protected,
   public, reinterpret_cast, static_cast, template, this, throw, true, 
   try, typeid, typename, using, virtual, wchar_t, xor, xor_eq

All of the C keywords are also C++ keywords.

Choosing Identifier Names

Choosing meaningful identifier names helps programs to be "self-documenting."

Generally, 1 or 2 character names are considered cryptic. Some commonly used short names are: c for characters; i, j, k for indexes; n for counters; p or q for pointers; s for strings; and x, y, z for floating-point variables.

Avoid using names that begin with underscores because the implementation may use names like that for its own purposes internally.

Abbreviations for meaningful names, if used, should be used consistently. For example, if nbr is used for number, then always use nbr instead of number.

A name should convey information as to how the variable is used and what type of data it will store. Example: item_cnt, lines_per_pg, max_input, buffer_size, and so on.

Extremely long names can convey lots of information, but they tend to make code difficult to read and maintain. Names should not exceed 31 characters in length.

Some linkers may make as few as the first six characters as significant.

Key Points

{TopOfPage} {Resources}


Introduction to the cout Object

In order to use the C++ Streams I/O, the iostream.h header file must be included. In addition, inclusion of iomanip.h is often needed.

   #include <iostream>
   #include <iomanip>

Upon program startup, the cout object of class ostream is instantiated.

Output to the terminal screen (or the standard output) is performed using the cout object, and the left bit-shift operator << in combinations.

   cout << EXPR;
   // in many instances, EXPR needs to be inside ()'s

Multiple values can be output by executing the following.

   cout << EXPR << EXPR << EXPR << ...;

Only one EXPR is allowed after each << The << points in the direction of the data flow to cout (the standard output) and is referred to as the insertion operator.

A cout object does not automatically place spaces between values being output, and it does not automatically add a newline at the end of its output.

Both "\n" and '\n' result in a newline being printed to the standard output. In addition, the endl I/O manipulator can be used to print a newline. Example: the following statements all print a newline followed by the value of an EXPR followed by another newline:

   cout << endl << EXPR << endl;
   cout << "\n" << EXPR << "\n";
   cout << '\n' << EXPR << endl;
   cout << endl << EXPR << "\n";
   cout << '\n' << EXPR << '\n';

C and C++ I/O can be mixed on a per-character basis, but to ensure data is sent/received in the proper order a call to sync_with_stdio() should be made.

{TopOfPage} {Resources}


About the cin Object

In order to use the C++ Streams I/O, the iostream.h header file must be included.

Upon program startup, the cin object of class istream is created (instantiated).

Input from the keyboard (or the standard input stream) is performed using the cin object, and the right-shift bit-wise operator >> in combinations such as:

   cin >> someVariable;

Multiple values can be input by executing the following.

   cin >> variable1 >> variable2 >> variable3 >> ...;

Only one variable is allowed after each >>. The >> points in the direction of the data flow from cin (the standard input) and is referred to as the extraction operator.

cin provides support for all of the primitive data types.

cin skips whitespace (where whitespace is defined by a call to isspace() see ctype.h).

   char c;
   cin >> c;  //reads the first non-whitespace character into c

cin.width(int) can be used to restrict the number of characters read (useful when reading strings).

   char a[16];
   cin.width(sizeof(a));
   cin >> a; //read at most 15 characters into a and add terminating null

The input stream has a state associated with it. They are:

Applying an input operation to a string that is not in the good() state is a null operation.

The insertion operator is intended for formatted input; reading objects of an expected type and format. The get() and getline() functions offer alternative ways to get input. These functions treat whitespace characters exactly like other characters.

get() leaves the terminator on the input stream; whereas, getline() doesn't.

   char a[32];
   cin.getline(a, sizeof(a));
      // reads at most 31 characters into array  a
      // appending a null character to the end
      //
      // the standard input stream is read until
      // 31 characters read or a newline is encountered

ignore() reads characters but it doesn't store them anywhere. By default, ignore() reads one character and the terminator is end-of-file.

clear() can be used to clear the input flags.

   int i;
   cout << "Enter an integer: " << flush;
   cin >> i;
   if (cin.fail()) {
      cin.clear();
      cout << "Enter an integer: " << flush;
      cin >> i;
      if (cin.fail())
         cerr << "forget it...";
   }

{TopOfPage} {Resources}


About Escape Sequences

Escape sequences are used for the following reasons.

C and C++
  \a  Alert   \b  Backspace   \f  Formfeed
  \n  Newline   \r  Carriage return   \t  Horizontal Tab
  \v  Vertical Tab   \"  Double quote   \'  Single quote
  \\  Backslash   \?  Question Mark   \0  Null Character
There are two types of numeric escape sequences: octal and hexadecimal.
Java Escape Sequences
Java will not compile a source file if it contains invalid escape sequences. [ Example]

  \b  Backspace   \f  Formfeed   \n  Newline
  \r  Carriage return   \t  Horizontal Tab   \"  Double quote
  \'  Single quote   \\  Backslash   \uhhhh  Unicode; 4 hexadecimal digits
  \ooo  C style; 3 octal digits

All of the Java escape sequences -- except for Unicode \u -- can only be used within string and character literals.

   String doubleQuote = "\"";
   char singleQuote = '\'';
   char bestGrade = '\u0041';    // set to 'A'
   char worstGrade = '\106';     // set to 'F'

{TopOfPage} {Resources}


Coding and Printing Long String Literals

Printing long string literals (e.g. a multi-line paragraph) posses two programs: keeping the source code nicely formatted, and making sure the program's output is readable (e.g. that the lines are not too long, word breaks are reasonable, and so on).

In general, to keep you code nicely formatted, you need to split your long string literal into multiple string literals and then use one of the following techniques.

The LongStringLiteral.cpp source code example uses all of the aforementioned techniqes.

You cannot press the ENTER key in the middle of a string literal. That results in a compile-time (i.e. syntax) error.

The following technique is an example of using a single cout statement with multiple insertion operators.

   cout << "This is a long string literal that does not fit on"
        << " a single line.  Therefore, I split it into multiple"
        << " string literals.  Unfortuneatly, this string literal"
        << " doesn't contain any newline characters; consequently,"
        << " when it does print, it will not display properly."
        << endl;

{TopOfPage} {Resources}


Primitive Data Types

The primitive data types are built-in to the language. They are also referred to as basic, atomic, fundamental, base, and so on.

The C and C++ languages support the following primitive data types.

* The bool primitive data type is in C++ only; however, it has been added to the newest versions of C.

The   char  short   int  long   primitive data types are  integral  data types; whereas,   float  double  long double   are  floating-point  types.

When you define a variable, memory is allocated.

The amount memory allocated is implementation-dependent. For example, on system A an int may take 4 bytes; whereas on system B is takes 2 bytes.

The amount of memory allocated dictates the minimum and maximum values that can be stored in variables.

{TopOfPage} {Resources}


Constants

Constants are values that are set at compile-time and cannot be changed at run-time (i.e. they are immutable).

Each constant value is defined to be a specific type.

By default, an integral number is type int. If it is too large (or small) of a value to fit into the size of an int, then it is type long.

By default, a floating-point number is type double.

Character constants are treated as small int values. For example, on some systems, the numeric value of 'A' is 65. The numeric values that are used to represent characters depends on the character set used by the system. [Some popular character sets are ASCII, EBCDIC, and Unicode.

{TopOfPage} {Resources}


Arithmetic Operators

All arithmetic operators are binary operators (i.e. they take two operands).

   *     multiply    
   /     divide
   %     modulus (remainder)
   +     addition
   -     substraction

Important points.

{TopOfPage} {Resources}


Precedence and Associativity of Operators

Whenever you have an EXPR that contains multiple operators, then you must be aware of operator precedence and associativity.

Precedence and associativity are used to "bind" operators with operands.

Every C/C++ book that I have reviewed contains a precedence and associativity chart. Here is a chart that displays the precedence and associativity of some of the operators we learn first.

Unary + and - have higher precedence than the binary forms.
Operators Associativity
()   +   -   (type)   sizeof right to left
*   /   % left to right
+   - left to right
= right to left

Precedence determines the order in which operands are bound to operators. Operators on the same line have the same precedence; rows are in order of decreasing precedence.

Examples:

If an EXPR contains two operators of equal precedence, then associativity is used to bind operators and operands.

An example using the EXPR:    a + b - c

   The + and - operators have equal precedence; therefore, associativity
   is used.  They associate left-to-right and we end up with with the
   binding  (a + b) - c

Precedence and associativity can be altered by using parenthesis.

   Example expression:  a * b / c

   * and / have equal precedence and they associate left-to-right;
   therefore, we get the following binding:  (a * b) / c  

   If we want the operand  b  to be attached to the operand  c,
   then we would parenthesis and code the EXPR:  a * (b / c).

Use parenthesis if you are ever in doubt about the precedence and associativity rules. [Note: it is possible to overuse ()'s.]

GDT::Resource::C++:: Precedence chart that includes all operators.

{TopOfPage} {Resources}


Relational Operators

Relational operators are used to compare the value of two expressions (EXPRs).

 ==   expr1 == expr2 equals
 !=   expr1 != expr2 not equals
 >   expr1 > expr2 greater than
 <   expr1 < expr2 less than
 >=   expr1 >= expr2 greater than or equal to
 <=   expr1 <= expr2 less than or equal to

The operators that are made up of two characters cannot have any whitespace between. For example: = = would be treated as two separate assignment operators and would result in a compile-time error. == is used to test two operands for equality.

It is easy to sometimes use the equality operator in lieu of the assignment operator and vice versa. You must remember the following.

   ==   is the relational equality operator; it compares two operands
        for equality and evaluates to either 0 (false) or 1 (true)

   =    is the assignment operator; it copies the value of the operand
        on the right-hand side to the operand on the left-hand side; the
        EXPR evaluates to the value that was copied (i.e. assigned)

Examples.

   int thisCourse = 100;   /* 100 assigned to thisCourse */
   int nextCourse = 205;   /* 205 assigned to nextCourse */

   thisCourse == nextCourse   /* evaluates to 0 (false) */
   thisCourse != nextCourse   /* evaluates to 1 (true) */
   thisCourse > nextCourse    /* evaluates to 0 */
   thisCourse < nextCourse    /* evaluates to 1 */
   thisCourse >= nextCourse   /* evaluates to 0 */
   thisCourse <= nextCourse   /* evaluates to 1 */

GDT::C++::Code:: RelationalOps.cpp

{TopOfPage} {Resources}


The if Statement and else Clause

The if is a selection control statement. It is a keyword of the language. It has the following syntax.

   if (EXPR) 
      statement';
   statement'';

   If  EXPR  evaluates to true (i.e. not zero), then  statement'  is
   executed followed by statement''; otherwise,  statement'  is skipped 
   and the flow control of the program jumps to  statement''.

   if (netWorth > 1000000)
      cout << "you are rich (at least money wise)"; 
   netWorth = netWorth * 2;   //let us double our net worth

Typically, there is no semicolon after the if. If there is, then the body of the if is simply a NULL (empty) statement. In many cases, this is a defect with your program (i.e. it is done by accident, not design).

   if (netWorth < 0)
      ;  //do nothing...

If more than one statement needs to be executed when an if EXPR is true, then a compound statement. should be used. A compound statement is a collection of zero or more statements enclosed in braces {}.

Compound statements are terminated by the closing brace } -- not a semicolon.

   if (EXPR) {
      statement';
      statement'';
   }                //note that there is no semicolon
   statement''';

   If EXPR evaluates to true, then both statement' and statement''
   are executed followed by statement'''; otherwise, statement' and
   statement'' are skipped and the flow control of the program jumps
   to statement'''.

   isSuperStar = false;
   bonus = 0;

   ...

   if (battingAvg > 300) {
      isSuperStar = true;
      bonus = 10000;
   }
   number = 55;

Every if statement can have a corresponding else clause which is executed whenever the if is false (i.e. 0). Syntax.

   if (EXPR)
      statement';
   else
      statement'';
   statement''';

   If EXPR is true, then statement' is executed, the else clause is
   skipped and the flow control of the program jumps to statement''';
   otherwise, statement' is skipped, statement'' is executed and
   the flow control of the program jumps to statement'''.

   if (netWorth > 1000000)
      cout << "you are rich (with respect to money)";
   else
      cout << "you are rich in other ways";

An else clause cannot be used without a corresponding if statement. Example.

   int i = 10;

   ...

   else   //not allowed -- there is no if statement
      cout << "this is not legal\n";

The body of an if construct can be any type of statement. Examples.

   if (EXPR) EXPR;      //the body is an expression statement
   if (EXPR) return EXIT_SUCCESS;  //body is a return statement
   if (EXPR) ;          //body is a null statement
   if (EXPR) { }        //body is an empty compound statement
   if (EXPR) if (EXPR)  //body is another if statement

An if statement containing another if is referred to as a nested if. There is no limit to the amount of nesting that can occur. Examples.

   if (EXPR)
      if (EXPR')
         statement';
   statement'';

   If EXPR is true, then EXPR' is evaluated; otherwise,
   flow control jumps to statement''.  If EXPR' is evaluated
   and it evaluates to true, then statement' is executed;
   otherwise, flow control jumps to statement''.

   if (age >= 100)
      if (gender == 'M')
         cout << "old man look at my life";

   if (age >= 100)
      if (gender == 'M')
         if (iq > 120)
            cout << "smart old man look at my life";
   cout << endl;

When using if statements, it is a good programming practice to use indentation to aid readability. The body of an if statement should be indented three or four spaces.

In all cases, each if can have a corresponding else clause.

   if (EXPR)
      if (EXPR')
         statement';
      else
         statement'';
   statement''';

   The top-most  if  does not have an  else  clause, whereas the
   inner-most  if  does.  If EXPR evaluates to false, then
   flow control jumps to statement'''; otherwise, EXPR' is
   evaluated.  If it evaluates to true, then statement' is
   executed; otherwise, statement' is skipped and statement'' is
   evaluated.  Regardless of which statement is executed,
   flow control jumps to statement'''.

Caution is required to make sure that else clauses match up to the correct if construct.

   if (age > 100)
      if (gender == 'M')
         cout << "you are an old man";
      else
         cout << "you are a young person";

   If age is greater than 100, then  if (gender == 'M')  will
   be executed.  If the gender is 'M', then the correct statement
   will print, but if the gender is not 'M', then the 
   "you are a young person" message will print.

   To correct this problem, a compound statement is needed to
   "tie" the  else  clause with the outer-most  if  statement.

   if (age > 100) {
      if (gender == 'M')
         cout << "you are an old man";
   } else
      cout << "you are a young person";
   
   Now if age > 100, then the body of the  if  is executed;
   otherwise, flow control jumps to the  else  clause.

GDT::C++::Code:: Age0.cpp and Age1.cpp and Age2.cpp

{TopOfPage} {Resources}


Logical Operators

Logical operators are used to "connect" expressions. Where relational operators are used to compare two values, logical operators take boolean operands and combine them to form boolean values.

  !   !expr NOT
  &&   expr1 && expr2 AND
  ||   expr1 || expr2 OR

The ! operator is a high-precedence unary operator, while && and || are medium-precedence binary operators. AND has slightly higher precedence than OR.

Examples.

   int i = 10, j = 5, k = 0;

   i == 10 && j == 5     yields the value 1 (true)
   i == 5  && j == 5     yields the value 0 (false)
   i == 10 || j == 5     yields the value 1
   i == 5  || j == 10    yields the value 0
   !i                    yields the value 0
   !k                    yields the value 1
   !k && k               yields the value 0

Given expr1 && expr2, expr1 is evaluated first. If it evaluates to false, then the entire EXPR will be false (0 && anything is 0); therefore, expr2 is not evaluated. This is called short circuit evaluation.

When using the terms true and false, zero is false and not-zero is true.

GDT::C++::Code:: LogicalOps.cpp

{TopOfPage} {Resources}


Truth Tables and De Morgan's Laws

The following is a "truth table" for the logical operators AND, OR and NOT.

  -------------------------------------------------------------------
  Logical operators:         AND   OR                            NOT 
  -------------------------------------------------------------------
  expr1       expr2          &&    ||                expr       !expr
  -------------------------------------------------------------------
  zero        zero           0     0                 zero         1
  nonzero     zero           0     1                 nonzero      0
  zero        nonzero        0     1 
  nonzero     nonzero        1     1 
  -------------------------------------------------------------------

In most popular programming environments, evaluation of a logical expression stops as soon as the truth is known. This is called short circuit evaluation. For example, given the following logical expression.

   expr1 || expr2

The C and Java languages guarantee that expr1 is evaluated first. If expr1 evaluates to TRUE, then the entire logical expression is TRUE and expr2 is not evaluated. (TRUE logically OR'd with anything is TRUE.)

The || and && logical operators are sequence points of the language. For example, given the following logical expression.

   f() && g()

Function f() is evaluated before function g(); however, the same is not necessarily true given the following arithmetic expression.

   f() + g()

Some implementations will evaluate the function f() first, while others will evaluate function g() first.

Logical operators (and the fact that they are sequence points and are subject to short circuit evaluation) are a critical tool when it comes to transaction processing.

   step1 && step2 && step3 && commit

   don't do step2 if step1 fails
   don't do step3 if step2 fails
   commit the transaction if step3 is successful
De Morgan's Laws

De Morgan's Laws are used to simplify logical expressions.

   !(expr1 || expr2)    is equivalent to     !expr1 && !expr2
   !(expr1 && expr2)    is equivalent to     !expr1 || !expr2

   examples... 

      useCYMK = !(red || green || blue)
      ...apply De Morgan's Law...
      useCYMK = !red && !blue && !green

      isdefective = !(clear && zeroerrors && posted)
      ...apply De Morgan's Law...
      isdefective = !clear || !zeroerrors || !posted

{TopOfPage} {Resources}


A Joke Having To Do With Loops

Example of 21st century Informatics?

   Q: How do you keep a computer programmer in the 
      shower all day long?

   A: Give them a shampoo with a label that says 
      "rinse, lather, repeat." 

Berkeley.edu::Jester--The Online Joke Recommender is a "computer program that rates jokes and gives suggestions based on each user's personal sense of humor."

{TopOfPage} {Resources}


The while Statement

The while statement supports iteration (i.e. it is a repetition control statement). Iteration is the process of repeating an operation.

The idea of looping in a computer program can be attributed to Ada Lovelace (01815-01852). Many believe Lovelace wrote the first "computer program." On 10 December 1980 (Ada's birthday), the U.S. Defense Department approved the reference manual for its new computer programming language, called "Ada".

The while statement repeatedly executes a simple statement or block (i.e. compound statement) until a conditional EXPR becomes false (i.e. 0). Each loop iteration is called a cycle.

   while (EXPR)    // typically, you don't want a semicolon 
      statement;

   EXPR is the "conditional" test used to determine whether the loop 
   should continue for another cycle, and  statement  is to be repeated.
   If multiple  statements  need to be executed, then use a compound 
   statement (or block).

   EXPR is evaluated only at the beginning of a loop cycle.

   Pseudo-code for a while loop:
      
      top-of-loop
         evaluate the EXPR
         if  EXPR  is "true"      // i.e. a non-zero value
            execute statement
            go to top-of-loop
         else
            go to end-of-loop  (i.e. terminate the loop)
      end-of-loop
      statement
      ...

   //Example:  loop until user enters a positive number
   int n = -1;
   while (n <= 0)
      cin >> n;

   //Example:  print out the numbers 1 through 5
   int i = 1;
   while (i <= 5) {
      cout << i << endl;
      i = i + 1;
   }
Sentinel Values

One way to terminate (end) a loop is when a particular data value is entered (e.g. the user enters a -1 or end-of-file is encountered), a special value that is used to end the loop is called a sentinel value.

Sentinel values should be defined as manifest (symbolic) constants. Example:

   const int EXIT_VALUE = -1;
   int n = EXIT_VALUE + 1;
   while (n != EXIT_VALUE) {
      cout << "Enter a number (" << EXIT_VALUE << " to exit): ";
      cin >> n;
   }
Infinite Loops

When you use a loop in a program, it is important to make sure that the condition used to control the loop will eventually become false, so that the loop can end. A loop that never finishes is called an infinite loop.

To stop an infinite loop, a special command sequence must be typed on the keyboard to interrupt the program and forcibly cause it to quit. This command differs from machine to machine.

Sometimes infinite loops are used by design; therefore, existenance of an infinite loop does not necessarily imply a program defect.

   // the following are infinite loops that do nothing 
   while (1) 
      ;  //null statement

   int i = 99;
   while (i != 0) ;

   while (true) ;  //C++ only...

   while (!false) { }  //C++ only....

   while (43 == 43) ;

{TopOfPage} {Resources}


The do while Statement

The do while statement supports iteration (i.e. it is a repetition control statement). Iteration is the process of repeating an operation.

The do while statement repeatedly executes a simple statement or block (i.e. compound statement) until a conditional EXPR becomes false (i.e. 0). Each loop iteration is called a cycle.

   do 
      statement;
   while (EXPR);  //semicolon must follow the while statement

   EXPR is the "conditional" test used to determine whether the loop 
   should continue for another cycle, and  statement  is to be repeated.
   If multiple  statements  need to be executed, then use a compound 
   statement (or block).  A compound statement is almost always used.

   EXPR is evaluated only at the end of a loop cycle.  

   Pseudo-code for a do-while loop:
      
      top-of-loop
         execute statement
         evaluate the EXPR
         if  EXPR  is "true"      // i.e. a non-zero value
            go to top-of-loop
         else
            go to end-of-loop  (i.e. terminate the loop)
      end-of-loop
      statement
      ...

   //Example:  print out the numbers 1 through 3
   int i = 1;
   do {
      cout << i << endl;
      i = i + 1;
   } while (i <= 3);


   Could the previous loop be rewritten:
      int i = 1;
      do cout << i++ << endl; while (i <= 3);

   How about:
      int i = 1;
      do cout << i << endl; while(i++ <= 3);

When you know for sure that a loop must cycle at least once, then a do-while is a good loop construct to use.

   set item counter to 0
   do {
      prompt user for data
      get data from user
      if (data equals sentinel value)
         break;
      if (data is junk)
         continue;  //get more data from the user
      process the data
      increment the item counter
   } while (1);
   print the item counter
Comment on Style

The do-while can be difficult to read; therefore, to help it "stick" out, I suggest the following.

{TopOfPage} {Resources}


The for Statement

The for statement supports iteration (i.e. it is a repetition control statement). Iteration is the process of repeating an operation.

The for statement repeatedly executes a simple statement or block (i.e. compound statement) until a control-EXPR becomes false (i.e. 0). Each loop iteration is called a cycle.

   for ([initialization-step]; [conditional-step]; [increment-step])
      statement;

   The optional "initialization-step" is executed once before the loop 
   is ever executed (and before the "conditional-step" is evaluated
   for the first time).

   The optional "conditional-step" is an EXPR that is evaluated at
   the top of the loop.  If it is true, then the body of the
   for  statement is executed; otherwise, flow control jumps to
   the first executable statement after the  for  loop body.  If
   no conditional-step is specified, then  it is taken as
   permanently true.

   After the body of a  for  loop has been executed, the optional
   "increment-step" is executed.

   After the increment-step is executed; the conditional-step
   is re-evaluated.

   Example:

      //print the numbers 1 through 3

      int i;
      for (i = 1; i <= 3; i = i + 1)
         cout << i << endl;

If the body of the for contains multiple statements, then a compound statement is needed.

All three steps for a for loop are EXPRs. Most commonly, the initialization-step and the increment-step are assignments or functions calls, and the conditional-step is a relational EXPR.

The for is frequently used when there are simple initialization and increment steps because it keeps the loop control statements close together and visible at the top of the loop.

The initialization and increment steps often take advantage of the sequence operator.

   for (i = 0, j = 99; i < n; i = i + 1, j = j - 1)
      do_something;

{TopOfPage} {Resources}


Home Previous Next