—Introduction to Computer C++ Guide for CPT 105 Programming The C++ “Shell”

advertisement
C++ Guide for CPT 105—Introduction to Computer
Programming
The C++ “Shell”
An Example from Ted Tucker
[comments that identify the program and you]
// your name
// your class number and section number
#include <iostream> //directives
using namespace std;
int main()
{
your code goes here
return 0;
}
Another Example (main shell.txt) from Ted Tucker
/*
Program Name:
Programmer:
Date:
Purpose:
Note: Block comments are contained here
*/
//Pre-processing instructions go here such as including iostream header
file
#include <iostream.h>
//If using Microsoft C++, then include the following statement
//Do not include using namespace std; if you are using Borland
using namespace std;
void main ()
{
//declaration and initialization statements
//Body of the program goes here
} // end of main
1 of 3307/11/2016
An Example from John McGaha
/*
Figure 2-19
Program Name:
Programmer:
Date:
Purpose:
depicted
College Admission
John McGaha
2.9.2002
Illustrates C++ source code that implements logic
on flowchart and psedudocode in Figure 2-19. This
program
will determine if students are admitted or rejected
to college
*/
#include <iostream.h>
#include <conio.h>
//Needed for getch function to pause the output
screen
main()
{
//Declare variables used in program (type and name)
//Pause screen for viewing
cout << endl << endl;
cout << "Press any key to end program.";
getch();
} // end of main
C++ Programmer’s Comments
Notes from Ted Tucker
A comment is text that the compiler ignores but that is useful for programmers.
Comments are normally used to annotate code for future reference. The compiler
treats them as white space. You can use comments in testing to make certain lines
of code inactive; however, #if/#endif preprocessor directives work better for this
because you can surround code that contains comments but you cannot nest
comments.
A C++ comment is written in one of the following ways:

The /* (slash, asterisk) characters, followed by any sequence of characters
(including new lines), followed by the */ characters. This syntax is the same as
ANSI C.

The // (two slashes) characters, followed by any sequence of characters. A
new line not immediately preceded by a backslash terminates this form of
comment. Therefore, it is commonly called a “single-line comment.”
2 of 3307/11/2016
The comment characters (/*, */, and //) have no special meaning within a character
constant, string literal, or comment. Comments using the first syntax, therefore,
cannot be nested. Consider this example:
/* Intent: Comment out this block of code.
Problem: Nested comments on each line of code are illegal.
FileName = String( "hello.dat" ); /* Initialize file string */
cout << "File: " << FileName << "\n"; /* Print status message */
*/
The preceding code will not compile because the compiler scans the input stream
from the first /* to the first */ and considers it a comment. In this case, the first */
occurs at the end of the Initialize file string comment. The last */, then, is no longer
paired with an opening /*.
Note that the single-line form (//) of a comment followed by the line-continuation
token (\) can have surprising effects. Consider this code:
#include <stdio.h>
void main()
{
printf( "This is a number %d", // \
5 );
}
After preprocessing, the preceding code contains errors and appears as follows:
#include <stdio.h>
void main()
{
printf( "This is a number %d",
}
Declaring Global Variables (Ch’s. 1, 3, 4)
C++ Key (Reserved) Word (from Ted Tucker)
Keywords are predefined reserved identifiers that have special meanings. They
cannot be used as identifiers in your program. The following keywords are reserved
for C++:
Syntax
keyword: one of
asm1
auto
bad_cast
bad_typeid
bool
break
case
catch
char
class
const
const_cast
continue
default
delete
do
double
dynamic_cast
else
enum
except
explicit
extern
false
3 of 3307/11/2016
finally
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
operator
private
protected
public
register
reinterpret_cast return
short
signed
sizeof
static
static_cast
struct
switch
template
this
throw
true
try
type_info
typedef
typeid
typename
union
unsigned
using
virtual
void
volatile
while
1 Reserved for compatibility with other C++ implementations, but not
implemented. Use __asm.
Microsoft Specific
In Microsoft C++, identifiers with two leading underscores are reserved for compiler
implementations. Therefore, the Microsoft convention is to precede Microsoft-specific
keywords with double underscores. These words cannot be used as identifier names.
allocate3
__inline
property3
__asm1
__int8
selectany3
__based2
__int16
__single_inheritance
__cdecl
__int32
__stdcall
__declspec
__int64
thread3
dllexport3
__leave
__try
dllimport3
__multiple_inheritance uuid3
__except
naked3
__uuidof
__fastcall
nothrow3
__virtual_inheritance
__finally
1
2
Replaces C++ asm syntax.
The __based keyword has limited uses for 32-bit target compilations.
4 of 3307/11/2016
These are special identifiers when used with __declspec; their use in other
contexts is not restricted.
Microsoft extensions are enabled by default. To ensure that your programs are fully
portable, you can disable Microsoft extensions by specifying the ANSI-compatible /Za
command-line option (compile for ANSI compatibility) during compilation. When you
do this, Microsoft-specific keywords are disabled.
When Microsoft extensions are enabled, you can use the previously-listed keywords
in your programs. For ANSI compliance, these keywords are prefaced by a double
underscore. For backward compatibility, single-underscore versions of all the
keywords except __except, __finally, __leave, and __try are supported. In
addition, __cdecl is available with no leading underscore.
END Microsoft Specific
3
C++ Input and Output (Ch’s. 1, 4)
This is a complex area for C++, especially if you want to exercise close control over the
appearance of your input and output.
Assignment (Ch. 1)
Arithmetic Expressions (Ch. 1)
Notes on Precedence of Operators (from Ted Tucker)
Operators
::
.
->
[]
()
++
-++
-!
+
*
&
new
delete
delete[]
()
*
Description
Scope resolution operator
Dot operator
Member selection
Array indexing
Function call
Postfix increment operator (placed after the variable)
Postfix decrement operator (placed after the variable)
Prefix increment operator (placed before the variable)
Prefix decrement operator (placed before the variable)
Not
Unary minus
Unary plus
Dereference
Address of
Create (allocate memory)
Destroy (deallocate)
Destroy array (deallocate)
Type cast
Multiply
5 of 3307/11/2016
/
%
+
<<
>>
<
>
<=
>=
==
!=
&&
||
=
+=
-=
*=
/=
%=
?:
throw
,
Divide
Remainder (modulo)
Addition
Subtraction
Insertion operator (console output)
Extraction operator (console input)
Less than
Greater than
Less than or equal to
Greater than or equal to
Equal
Not equal
And
Or
Assignment
Add and assign
Subtract and assign
Multiply and assign
Divide and assign
Modulo and assign
Conditional operator
Throw an exception
Comma operator
An Example from Ted Tucker
#include <iostream>
using namespace std;
int main()
{
const double RATE = 6.9;
double deposit;
cout << "Enter the amount of your deposit $";
cin >> deposit;
double newBalance;
newBalance = deposit + deposit * ( RATE / 100);
cout << "In one year, that deposit will grow to\n"
<< "$" << newBalance << " an amount worth waiting for,\n";
return 0;
}
6 of 3307/11/2016
Relational Expressions and Logical Comparison Operators
(Ch’s. 1, 5)
The C++ “if” Selection Statements (Ch. 1) & the “if-then” and “ifthen-else” Selection Structures (Ch’s. 2, 5)
Notes from Ted Tucker
The C++ if Statement
The if statement evaluates the expression enclosed in parentheses. The expression
must be of arithmetic or pointer type, or it must be of a class type that defines an
unambiguous conversion to an arithmetic or pointer type.
In both forms of the if syntax, if the expression evaluates to a nonzero value (true),
the statement dependent on the evaluation is executed; otherwise, it is skipped.
In the if...else syntax, the second statement is executed if the result of evaluating
the expression is zero.
The else clause of an if...else statement is associated with the closest previous if
statement that does not have a corresponding else statement. The following code
fragment demonstrates how this works:
if( condition1 == true )
if( condition2 == true )
cout << "condition1 true; condition2 true\n";
else
cout << "condition1 true; condition2 false\n";
else
cout << "condition 1 false\n";
Many programmers use curly braces ({ }) to explicitly clarify the pairing of
complicated if and else clauses, such as in the following example:
if( condition1 == true )
{
if( condition1 == true )
cout << "condition1 true; condition2 true\n";
else
cout << "condition1 true; condition2 false\n";
}
else
cout << "condition 1 false\n";
Although the braces are not strictly necessary, they clarify the pairing between if and
else statements.
C++ for Figure 2-19 (from John McGaha)
/*
Figure 2-19
Program Name: College Admission
Programmer:
John McGaha
Date:
2.9.2002
7 of 3307/11/2016
Purpose:
depicted
Illustrates C++ source code that implements logic
on flowchart and psedudocode in Figure 2-19. This
program
will determine if students are admitted or rejected
to college
*/
#include <iostream.h>
#include <conio.h>
//Needed for getch function to pause the output
screen
main()
{
//Declare variable names and types used in the main module
float test;
float rank;
//Get the test and rank values from the keyboard
cout << "Enter test score ";
cin >> test;
cout << endl;
cout << "Enter high school rank: ";
cin >> rank;
cout << endl;
/*
Evaluate test score and rank
Accept:
If test >= 90 and rank >= 25 (upper 75%)
or
If test >= 80 and rank >= 50 (upper 50%)
or
If test >= 70 and rank >= 75 (upper 25%)
Reject:
All other conditions
*/
if (test >= 90)
if (rank >= 25)
cout << "Accept" << endl; //test >= 90 and rank >= 25 (upper
75%)
else
cout << "Reject" << endl;
else
if (test >= 80)
if (rank >= 50)
cout << "Accept" << endl; //test >= 80 and rank >= 50
(upper 50%)
else
cout << "Reject" << endl;
else
if (test >= 70)
if (rank >= 75)
cout << "Accept" << endl;//test >= 70 and rank >= 75
(upper 25%)
else
8 of 3307/11/2016
cout << "Reject" << endl;
else
cout << "Reject" << endl;
cout << endl << endl;
cout << "Press any key to end program.";
getch();
} // end of main
C++ Compound Statements and Blocks
The C++ “while” Iteration Statement and the “do while” Pre-Test
Loop Structure (Ch’s. 2, 6)
Notes from Ted Tucker
The C++ while Statement
The while statement executes a statement repeatedly until the termination condition
(the expression) specified evaluates to zero. The test of the termination condition
takes place before each execution of the loop; therefore, a while loop executes zero
or more times, depending on the value of the termination expression. The following
code uses a while loop to trim trailing spaces from a string:
char *trim( char *szSource )
{
char *pszEOS;
// Set pointer to end of string to point to the character just
// before the 0 at the end of the string.
pszEOS = szSource + strlen( szSource ) - 1;
while( pszEOS >= szSource && *pszEOS == ' ' )
*pszEOS-- = '\0';
return szSource;
}
The termination condition is evaluated at the top of the loop. If there are no trailing
spaces, the loop never executes.
The expression must be of an integral type, a pointer type, or a class type with an
unambiguous conversion to an integral or pointer type.
An Example from Ted Tucker
#include <iostream>
using namespace std;
int main()
{
9 of 3307/11/2016
int countDown;
cout << "How many greetings do you want? ";
cin >> countDown;
while (countDown > 0)
{
cout << "Hello ";
countDown = countDown - 1;
}
cout << endl;
cout << "That's all!\n";
return 0;
}
The C++ “break”, “continue”, and “return” Statements
Notes from Ted Tucker
The C++ break Statement
The break statement is used to exit an iteration or switch statement. It transfers control to
the statement immediately following the iteration substatement or switch statement.
The break statement terminates only the most tightly enclosing loop or switch statement.
In loops, break is used to terminate before the termination criteria evaluate to 0. In the
switch statement, break is used to terminate sections of code — normally before a case
label. The following example illustrates the use of the break statement in a for loop:
for( ; ; )
// No termination condition.
{
if( List->AtEnd() )
break;
List->Next();
}
cout << "Control transfers to here.\n";
Note There are other simple ways to escape a loop. It is best to use the break statement
in more complex loops, where it can be difficult to tell whether the loop should be
terminated before several statements have been executed.
The C++ continue Statement
The continue statement forces immediate transfer of control to the loop-continuation
statement of the smallest enclosing loop. (The “loop-continuation” is the statement that
contains the controlling expression for the loop.) Therefore, the continue statement can
appear only in the dependent statement of an iteration statement (although it may be the
sole statement in that statement). In a for loop, execution of a continue statement causes
evaluation of expression2 and then expression3.
10 of 3307/11/2016
The following example shows how the continue statement can be used to bypass sections
of code and skip to the next iteration of a loop:
#include <conio.h>
// Get a character that is a member of the zero-terminated
// string, szLegalString. Return the index of the character
// entered.
int GetLegalChar( char *szLegalString )
{
char *pch;
do
{
char ch = _getch();
// Use strchr library function to determine if the
// character read is in the string. If not, use the
// continue statement to bypass the rest of the
// statements in the loop.
if( (pch = strchr( szLegalString, ch )) == NULL )
continue;
// A character that was in the string szLegalString
// was entered. Return its index.
return (pch - szLegalString);
// The continue statement transfers control to here.
} while( 1 );
return 0;
}
The C++ return Statement
The return statement allows a function to immediately transfer control back to the
calling function (or, in the case of the main function, transfer control back to the
operating system). The return statement accepts an expression, which is the value passed
back to the calling function. Functions of type void, constructors, and destructors cannot
specify expressions in the return statement; functions of all other types must specify an
expression in the return statement.
The expression, if specified, is converted to the type specified in the function declaration,
as if an initialization were being performed. Conversion from the type of the expression
to the return type of the function can cause temporary objects to be created.
When the flow of control exits the block enclosing the function definition, the result is
the same as it would be if a return statement with no expression had been executed. This
is illegal for functions that are declared as returning a value.
A function can have any number of return statements.
An Example of “continue” from Ted Tucker
#include <iostream>
11 of 3307/11/2016
using namespace std;
int main()
{
int number, sum = 0, count= 0;
cout << "Enter 4 negative numbers, ONE PER LINE:\n";
while (count < 4)
{
cin >> number;
if (number >= 0)
{
cout << "ERROR: positive number (or zero):\n"
<< "Reenter that number and continue:\n";
continue;
}
sum = sum + number;
count++;
}
cout << sum << " is the sum of the "
<< count << " numbers.\n";
return 0;
}
The C++ “switch” Selection Statement and the Case Selection
Structure (Ch. 2)
The “switch” construct in C/C++/Java is limited to integer tests. It is very limited
compared to case constructs in BASIC and COBOL. The “if … else if …” construct may
be used where the C++ switch will not accommodate.
Notes from John McGaha & Ted Tucker
The C++ switch Statement
The C++ switch statement allows selection among multiple sections of code,
depending on the value of an expression. The expression enclosed in parentheses,
the “controlling expression,” must be of an integral type or of a class type for which
there is an unambiguous conversion to integral type.
The switch statement causes an unconditional jump to, into, or past the statement
that is the “switch body,” depending on the value of the controlling expression, the
values of the case labels, and the presence or absence of a default label. The
switch body is normally a compound statement (although this is not a syntactic
requirement). Usually, some of the statements in the switch body are labeled with
case labels or with the default label. Labeled statements are not syntactic
12 of 3307/11/2016
requirements, but the switch statement is meaningless without them. The default
label can appear only once.
Syntax
case constant-expression : statement
default : statement
The constant-expression in the case label is converted to the type of the controlling
expression and is then compared for equality. In a given switch statement, no two
constant expressions in case statements can evaluate to the same value. The
behavior is shown below.
Condition
Action
Converted value matches that of the
promoted controlling expression.
Control is transferred to the statement
following that label.
None of the constants match the
constants in the case labels; default
label is present.
Control is transferred to the default label.
None of the constants match the
constants in the case labels; default
label is not present.
Control is transferred to the statement after the
switch statement.
An inner block of a switch statement can contain definitions with initializations as
long as they are reachable — that is, not bypassed by all possible execution paths.
Names introduced using these declarations have local scope. The following code
fragment shows how the switch statement works:
switch( tolower( *argv[1] ) )
{
// Error. Unreachable declaration.
char szChEntered[] = "Character entered was: ";
case 'a' :
{
// Declaration of szChEntered OK. Local scope.
char szChEntered[] = "Character entered was: ";
cout << szChEntered << "a\n";
}
break;
case 'b' :
// Value of szChEntered undefined.
cout << szChEntered << "b\n";
break;
default:
// Value of szChEntered undefined.
cout << szChEntered << "neither a nor b\n";
break;
}
A switch statement can be nested. In such cases, case or default labels associate
with the most deeply nested switch statements that enclose them. For example:
switch( msg )
13 of 3307/11/2016
{
case WM_COMMAND:
// Windows command. Find out more.
switch( wParam )
{
case IDM_F_NEW:
// File New menu command.
delete wfile;
wfile = new WinAppFile;
break;
case IDM_F_OPEN: // File Open menu command.
wfile->FileOpenDlg();
break;
...
}
case WM_CREATE:
// Create window.
...
break;
case WM_PAINT:
// Window needs repainting.
...
break;
default:
return DefWindowProc( hWnd, Message, wParam, lParam );
}
The preceding code fragment from a Microsoft Windows® message loop shows how
switch statements can be nested. The switch statement that selects on the value of
wParam is executed only if msg is WM_COMMAND. The case labels for menu
selections, IDM_F_NEW and IDM_F_OPEN, associate with the inner switch statement.
Control is not impeded by case or default labels. To stop execution at the end of a
part of the compound statement, insert a break statement. This transfers control to
the statement after the switch statement. This example demonstrates how control
“drops through” unless a break statement is used:
BOOL fClosing = FALSE;
...
switch( wParam )
{
case IDM_F_CLOSE:
fClosing = TRUE;
// fall through
// File close command.
case IDM_F_SAVE:
// File save command.
if( document->IsDirty() )
if( document->Name() == "UNTITLED" )
FileSaveAs( document );
else
FileSave( document );
if( fClosing )
document->Close();
break;
}
The preceding code shows how to take advantage of the fact that case labels do not
impede the flow of control. If the switch statement transfers control to IDM_F_SAVE,
14 of 3307/11/2016
fClosing is FALSE. Therefore, after the file is saved, the document is not closed.
However, if the switch statement transfers control to IDM_F_CLOSE, fClosing is
set to TRUE, and the code to save a file is executed.
C++ for Figure 2-31 (from John McGaha)
/*
Figure 2-31
Program Name:
Programmer:
Date:
Purpose:
depicted
College Fees
John McGaha
2.9.2002
Illustrates C++ source code that implements logic
on flowchart and psedudocode in Figure 2-31. This
program
will determine fee students must pay, based upon
their class.
*/
#include <iostream.h> //Needed for input/output
#include <ctype.h>
//Needed for toupper function
#include <conio.h>
//Needed for getch function
main()
{
//Declare variable names and types used in the main module
char Class;
int Fee;
//Get Class from keyboard
cout << "Enter the Class: <F> Freshman <S> Sophmore <J> Junior";
cout << endl << endl;
cout << "Class? ";
cin >> Class;
//Change Class character to Upper Case so Case will work properly
Class = toupper(Class);
//Determine Fee
switch(Class)
{
case 'F': //Freshman
Fee = 75;
break;
case 'S': //Sophmore
Fee = 50;
break;
case 'J': //Junior
Fee = 30;
break;
default: //Assumes Senior
Fee = 10;
15 of 3307/11/2016
break;
}
cout << endl << endl; //Output two blank lines
cout << "The fee is $" << Fee << endl;
cout << "Press any key to end program.";
getch();
} // end of main
An example from Ted Tucker, Using the Random Number Generator
Functions and the Modulus Operator
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int month, day;
cout << "Welcome to your friendly weather program.\n"
<< "Enter today's date as two integers for the month and
the day:\n";
cin >> month;
cin >> day;
srand(month*day);
int prediction;
char ans;
cout << "Weather for today:\n";
do
{
prediction = rand( )% 3;
switch (prediction)
{
case 0:
cout << "The day will be sunny!!\n";
break;
case 1:
cout << "The day will be cloudl.\n";
break;
case 2:
cout << "The day will be stormy!\n";
break;
default:
cout << "Weather program is not functioning
properly.\n";
}
cout << "Want the weather for the next day? (y/n): ";
cin >> ans;
}while (ans == 'y' || ans == 'Y');
cout << "That's it from your 24-hour weather program.\n";
return 0;
16 of 3307/11/2016
}
The C++ “do … while” Iteration Statement and the “do until”
Post-Test Loop Structure (Ch’s. 2, 6)
Notes from Ted Tucker
The do Statement
The do statement executes a statement repeatedly until the specified termination
condition (the expression) evaluates to zero. The test of the termination condition is
made after each execution of the loop; therefore, a do loop executes one or more
times, depending on the value of the termination expression. The following function
uses the do statement to wait for the user to press a specific key:
void WaitKey( char ASCIICode )
{
char chTemp;
do
{
chTemp = _getch();
}
while( chTemp != ASCIICode );
}
A do loop rather than a while loop is used in the preceding code — with the do loop,
the _getch function is called to get a keystroke before the termination condition is
evaluated. This function can be written using a while loop, but not as concisely:
void WaitKey( char ASCIICode )
{
char chTemp;
chTemp = _getch();
while( chTemp != ASCIICode )
{
chTemp = _getch();
}
}
The expression must be of an integral type, a pointer type, or a class type with an
unambiguous conversion to an integral or pointer type.
An Example from Ted Tucker
#include <iostream>
using namespace std;
int main()
{
int countDown;
cout << "How many greetings do you want? ";
cin >> countDown;
17 of 3307/11/2016
do
{
cout << "Hello ";
countDown = countDown - 1;
}while (countDown > 0);
cout << endl;
cout << "That's all!\n";
return 0;
}
C++ Functions and Out-of-Line Modularization (Ch. 3)
C++ for Ch. 3, Ex. 3, not using functions (from John McGaha)
/*
Exercise #3
Program Name:
Programmer:
Date:
Purpose:
depicted
Exercise Solution
John McGaha
2.9.2002
Illustrates C++ source code that implements logic
in psedudocode on page 76, Exercise 3. This program
will
determine final values of variables A, B, and C.
*/
#include <iostream.h>
#include <conio.h>
//Needed for getch function to pause the output
screen
main()
{
//Declare all variables - type and name
int A, B, C;
A = 2;
location
B = 4;
C = 10;
//One equal symbol used to make assignment to memory
//Display Original Values of A, B, and C
cout << "Original Values" << endl;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << endl << endl;
cout << "Press any key to continue." << endl << endl;
getch();
while(C > 6)
{
B = B + 1;
C = C - 1;
18 of 3307/11/2016
} // end while
if (A == 2) //Two equal symbols used for equality test
{
A = A + 1;
B = B - 1;
} //end if
if (C == 10)
{
A = A + 1;
B = B - 1;
}
else
{
B = B + 1;
C = C - 1;
}
//Display Final Values of A, B, and C
cout << "Final Values" << endl;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << endl << endl;
cout << "Press any key to end program.";
getch();
} // end of main
C++ for Ch. 3, Ex. 3, using functions (from John McGaha)
/*
Exercise #3
Program Name:
Programmer:
Date:
Purpose:
depicted
Exercise Solution
John McGaha
2.9.2002
Illustrates C++ source code that implements logic
in psedudocode on page 76, Exercise 3. This program
will
determine final values of variables A, B, and C.
*/
#include <iostream.h>
#include <conio.h>
//Needed for getch function to pause the output
screen
//Global Variables and functions (modules)
int A = 2;
int B = 4;
int C = 10;
ChangeBC()
19 of 3307/11/2016
{
B = B + 1;
C = C - 1;
}
ChangeA()
{
A = A + 1;
B = B - 1;
}
main()
{
//Display Original Values of A, B, and C
cout << "Original Values" << endl;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << endl << endl;
cout << "Press any key to continue." << endl << endl;
getch();
while(C > 6)
{
ChangeBC();
}
if (A == 2) //Two equal symbols used for equality test
ChangeA();
if (C == 10)
ChangeA();
else
ChangeBC();
//Display Final Values of A, B, and C
cout << "Final Values" << endl;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
cout << "C = " << C << endl;
cout << endl << endl;
cout << "Press any key to end program.";
getch();
} // end of main
Combining Decisions Using C++ Logical Expressions (Ch. 5)
20 of 3307/11/2016
C++ “while” Iteration Statement and Counter-Controlled Looping
(Ch. 6)
C++ “for” Iteration Statement (Ch. 6)
Notes from Ted Tucker
The C++ for Statement
The for statement can be divided into three separate parts, as shown below.
Syntax Name
When Executed
Contents
for-init-statement Before any other element of the for Often used to initialize loop
statement or the substatement.
indices. It can contain
expressions or declarations.
expression1
Before execution of a given
iteration of the loop, including the
first iteration.
An expression that evaluates to
an integral type or a class type
that has an unambiguous
conversion to an integral type.
expression2
At the end of each iteration of the
loop; expression1 is tested after
expression2 is evaluated.
Normally used to increment
loop indices.
The for-init-statement is commonly used to declare and initialize loop-index
variables. The expression1 is often used to test for loop-termination criteria. The
expression2 is commonly used to increment loop indices.
The for statement executes the statement repeatedly until expression1 evaluates to
zero. The for-init-statement, expression1, and expression2 fields are all optional.
The following for loop:
for( for-init-statement; expression1; expression2 )
{
// Statements
}
is equivalent to the following while loop:
for-init-statement;
while( expression1 )
{
// Statements
expression2;
}
A convenient way to specify an infinite loop using the for statement is:
for( ; ; )
{
// Statements to be executed.
}
21 of 3307/11/2016
This is equivalent to:
while( 1 )
{
// Statements to be executed.
}
The initialization part of the for loop can be a declaration statement or an expression
statement, including the null statement. The initializations can include any sequence
of expressions and declarations, separated by commas. Any object declared inside a
for-init-statement has local scope, as if it had been declared immediately prior to the
for statement. Although the name of the object can be used in more than one for
loop in the same scope, the declaration can appear only once. For example:
#include <iostream.h>
void main()
{
for( int i = 0; i < 100; ++i )
cout << i << "\n";
// The loop index, i, cannot be declared in the
// for-init-statement here because it is still in scope.
for( i = 100; i >= 0; --i )
cout << i << "\n";
}
Although the three fields of the for statement are normally used for initialization,
testing for termination, and incrementing, they are not restricted to these uses. For
example, the following code prints the numbers 1 to 100. The substatement is the
null statement:
#include <iostream.h>
void main()
{
for( int i = 0; i < 100; cout << ++i << endl )
;
}
Accumulating Totals (Ch. 6)
Multi-Level Reports and “Control Breaks” (Ch. 7)
Notes from Ted Tucker
SINGLE-LEVEL CONTROL BREAK PROCESSING
Control break processing, sometimes called summary or group report processing,
produces subtotals for a group of records. With this type of processing control fields are
used to indicate when totals are to print. The ‘control’ field is the field upon which the
data to be processed is sorted. Obviously, this means that the data file must be sorted in
order to process a control break report. The sort does not produce records with unique
22 of 3307/11/2016
identifiers. Duplicate keyed records are produced. A field, defined as a ‘hold’ field is
used to represent the current group of records that is being processed. The value of the
‘control’ field is stored in the ‘hold’ field following the initial read of the data file. The
beginning of a pretest loop follows the initial read.
The first processing that is performed inside the loop is an IF-THEN-ELSE
structure with a null ELSE. This structure checks to see if the current value of the
‘control’ field is the same as the ‘hold’ field. If the ‘control’ field is the same as the ‘hold
’field, a detail line can be printed if desired (when detail reports are desired) and the
subtotal for the current group is accumulated. This processing is followed by another read
operation and the next iteration of the loop. If the current value of the ‘control’ field and
the ‘hold’ field are not the same, the first record of the new group has been read. This
forces a control break which requires the program to finalize the processing of the
previous group of records.
Break processing requires that subtotals for the last group of records are to be
printed. The subtotal will be accumulated into a grand total at this time and the subtotal
field will be initialized back to zero. The ‘hold’ field will be updated to the current value
of the ‘control’ field at the end of the break processing. The detail processing and
accumulation continues after the four break processing steps. This is then followed by
another read operation and the next loop iteration. This processing continues until all of
the records in the file have been processed.
When end-of-file occurs, the break processing must be forced one last time in
order to complete the processing on the last group of records. The last group’s subtotal
must be printed and accumulated into a grand total. The grand total is then printed and
processing is complete.
23 of 3307/11/2016
MULTI-LEVEL CONTROL BREAK PROCESSING
Multi-level control break processing is not a great deal different from single level
control break processing. The major difference, of course, is that instead of one ‘control’
field, there are multiple ‘control’ fields. This means that the data file contains multiple
sorts. These sorts are embedded. For example, there may be departments sorted within
divisions and divisions sorted within companies. This particular example would be
considered a triple-level control break. (Triple-level break processing will be used in the
following explanation of multi-level break processing.) For each ‘control’ field a ‘hold’
field exists as well as a separate subtotal field. After the initial record is read, all of the
‘hold’ fields must be initialized with the current values of the ‘control’ fields. For ease of
understanding, we will reference each of these break levels as major (company),
intermediate (division), and minor (department).
As in single level control break processing, a check must be done to see if a
‘control’ field is still equal to its ‘hold’ field. This will be the first processing in the pretest loop that follows the initial data read operation. With a multi-level break, a decision
structure must be created that will check the ‘control’ fields in a specific order. It stands
to reason that if a company group changes that the division and the department groups
have also changed. If the division group within a company group changes, the department
group will also change. Therefore, the first check must be done on the major ‘control’
field. If the major ‘control’ field is still equal to its ‘hold’ field, a check must then be
done to see if the intermediate ‘control’ field is still equal to its ‘hold’ field. If the
intermediate ‘control’ field is still the same as its ‘hold’ field, a check must then be done
to see if the minor ‘corneal’ field is still the same as its ‘hold’ field. If a change has
occurred at any level, a subroutine must be executed that contains processing written for
each specific break level.
Each break subroutine contains the same four processing steps as the single level
control break except that different subtotals are printed for each level and each subtotal is
accumulated into the next higher level. A higher level subroutine calls the next lower
level subroutine before its four steps are processed. For example, the first processing in
the major subroutine is a call to execute the intermediate subroutine. The first processing
in the intermediate subroutine is a call to execute the minor subroutine. In this manor, the
subroutines are executed in reverse order. This is done so that the lower level subtotals
can be accumulated into the higher level subtotals before the higher level subtotals are
printed. The major level subtotal is accumulated into the grand total.
The detail processing proceeds as in single level break processing. The minor
level subtotals (for example, the department subtotal) is accumulated during the detail
processing. After the detail processing, the next record will be read before proceeding
with the next loop iteration. This processing will continue until all of the records have
been processed.
24 of 3307/11/2016
As in single level break processing, the last break must be forced. The minor
subtotal will be printed and accumulated into the intermediate subtotal followed by the
printing of the intermediate subtotal and accumulation of the intermediate subtotal into
the major subtotal. The major subtotal is then printed followed by the accumulation of the
major subtotal into the grand total. This processing is then followed by the last processing
step which is the printing of the grand total.
Pseudocode for Multi-Level Control Break (from Ted Tucker)
Read First Record
Initialize hold areas (Major, Intermediate, and Minor)
Begin Loop
While not at end of file
If Major hold <> Major control
Execute Major Break Processing
Else if Intermediate hold <> Intermediate control
Execute Intermediate Break Processing
Else if Minor hold <. Minor control
Execute Minor Break Processing
End if
Print Detail line
Accumulate Minor subtotals
Read next record
End Loop
Execute Final Processing
MAJOR BREAK
Call Intermediate Break
Print Major Subtotal
INTERMEDIATE BREAK
Call Minor Break
Print Intermediate Subtotal
Accum Major to Grand
Initialize Major Subtotal
Accum Inter to Major
Initialize Intermediate
Subtotal
Update Intermediate Hold
Field
Update Major Hold Field
FINAL PROCESSING
25 of 3307/11/2016
MINOR BREAK
Print Minor Subtotal
Accum Minor to
Intermediate
Initialize Minor Subtotal
Update Minor Hold Field
Print Minor Subtotal
Accumulate Minor Subtotal into Intermediate Subtotal
Print Intermediate Subtotal
Accumulate Intermediate Subtotal into Major Subtotal
Print Major Subtotal
Accumulate Major Subtotal into Grand Total
Print Grand Total
C++ Arrays (Ch. 8, 9)
Serial Search (Ch. 8)
An Example from Ted Tucker
#include <iostream>
using namespace std;
const int DECLARED_SIZE = 10;
int search(int a[], int number_used, int target)
{
int index = 0;
bool found = false;
while ((!found) && (index < number_used))
if (target == a[index])
found = true;
else
index++;
if (found)
return index;
else
return -1;
}
int main()
{
char ans;
int result;
int target;
do
{
cout << "Enter a number to search for: ";
cin >> target;
result = search(arr, DECLARED_SIZE, target);
if (result == -1)
cout << target << " is not in the list.\n";
26 of 3307/11/2016
else
cout << target << " is stored in array position "
<< result << endl
<< "(Remember: the first position is 0.\n)";
cout << "Search again? (y/n followed by return): ";
cin >> ans;
} while ((ans != 'n') && (ans != 'N'));
cout << "End of program/\n";
return 0;
}
Binary Search (Ch. 8)
Notes from Ted Tucker
BINARY SEARCH
The Sequential search through an array will always work. If the array contains
100 items, on the average a Sequential search will find the match after searching through
50 items. In the worst case, the search will have to look through all 100 items. A Binary
search can be used on an sorted array and can be more efficient than a Sequential search.
This search procedure involves first looking in the middle of the array. The value of the
middle element is compared against the target element. If the middle element is greater
than the target, the target must be in the lower half of the array. If the middle is less than
the target, the target must be in the upper half. Having determined which half of the
remaining array is to be searched, the middle of that half is compared against the target.
This will continue until a match is found or until no more elements remain to be
searched. Because the array is always divided in half, this search procedure is called a
binary search.
The following is Pseudocode for setting the index values in a Binary search.
Establish BOTTOM = Bottom of Range
TOP = Top of Range
TARGET = Search Value
WHILE there are more elements in the array and no match has been found
LET INDEX = Middle of the remaining range ( TOP + BOTTOM ) / 2
IF element( INDEX ) > TARGET THEN
set TOP of Remaining Range to INDEX
ELSE
set BOTTOM of Remaining Range to INDEX
END IF
Repeat WHILE Loop
27 of 3307/11/2016
Since we are continually dividing the range in half, we will never actually reach
the bottom or top of the range. Therefore, we must set the search range to at least one
beyond the actual top and bottom values in which we are searching. We use integer
division so that the index will always have an integer value.
An Example from Ted Tucker
//example binary search
#include <iostream>
using namespace std;
const int ARRAY_SIZE = 10;
void search(const int a[], int first, int last, int key, bool& found,
int &location)
{
int mid;
if (first > last)
{
found = false;
}
else
{
mid = (first + last) /2;
if (key == a[mid])
{
found = true;
location = mid;
}
else if (key < a[mid])
{
search(a, first, mid -1, key, found, location);
}
else if (key > a[mid])
{
search(a, mid + 1, last, key, found, location);
}
}
}
int main()
{
const int final_index = ARRAY_SIZE - 1;
int a[ARRAY_SIZE] = {100,233,345,254,109,456,783,400,500,901};
int key, location;
28 of 3307/11/2016
bool found;
cout << "Enter number to be located: ";
cin >> key;
search(a, 0, final_index, key, found, location);
if (found)
cout << key << " is in index location "
<< location << endl;
else
cout << key << " is not in the array." << endl;
return 0;
}
“Bubble” Sort (Ch. 9)
Notes from Ted Tucker
BUBBLE SORT
Bubble sort processing using an array consists of a nested loop structure that will
sort the elements of the array in either ascending or descending order. The outer loop is a
post-test loop that continues iteration until all of the array elements are sorted. A flag
variable used for testing for a sorted array condition is set to a value of ‘true’ or ‘yes’ at
the beginning of the loop. By setting this flag to ‘yes’, the sort algorithm assumes that the
array is already sorted. This is done because the inner loop must process all of its
iterations at least once even if the array is already sorted. This is one of the main reasons
that the Bubble sort is actually one of the most inefficient sort algorithms. Unfortunately,
it is one of the easiest sort algorithms to learn. Therefore, it is used quite often as an
introduction to sorting.
The inner loop is a counter controlled loop that will iterate one less time than the
number of elements in the array. This is because two consecutive elements are compared
at a time. Inside the counter controlled loop, an IF-THEN-ELSE structure with a null
ELSE is used to test the current array element (array(count)) with the very next element
in the array (array(count + 1)). To sort in ascending order, use a greater than comparison
(array(counter) > array(counter + 1)). If the array(counter) element is greater than the
array(count + 1) element, the values of the two array elements swap positions in the
array. This is usually done by storing array(counter) in a temporary field , array(counter +
1) in array(counter) and finally the temporary field in array(counter + 1). In this way,
element values swap positions.
After the swap, the flag used to test whether the continue looping the outer loop,
is set to ‘no’. This shows that the array is not sorted and forces another outer loop
iteration. Remember, the inner loop must complete all of its loop iterations at least once
even after the array is sorted. If even two elements must be swapped, the processing must
continue.
29 of 3307/11/2016
An Example from John McGaha
/* Sorting.cpp
Date: November 2002
Programmer: Your Name
Purpose:
To illustrate the use of arrays in C++. This program will
load an array from the keyboard, perform a bubble sort,
find the average score, find the minimum score, find the
maximum score, and then display them back to the screen
in sorted order and then store the scores, average, minimum,
and maximum in an output file.
*/
/****** Pre-Processing ******/
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
void main()
{
/****** Housekeeping Tasks ******/
//Declare and initialize variables and constants
float gradeArray[10];
float average = 0, minimum = 0, maximum = 0, sum = 0;
const int SIZE = 10;
int pairsToCompare;
int y = 0;
int x = 0;
int temp = 0;
//Declare and open an output file - file does not exist, it will be
created
ofstream outFile("Grades.txt",ios::out);
/***************** Processing Section******************/
//Loop 10 times. subscript++ adds ONE to the subscript at the END of
each pass
for(int subscript = 0; subscript < SIZE; subscript++)
{
cout << endl;
//Prompt user for grade - Note that the grade number (1-10) is
displayed too
cout << "Enter grade " << (subscript + 1) << ": ";
//Get the grade from the keyboard and store into the gradeArray.
//Note: the subscript increments from 0 to 10
cin >> gradeArray[subscript];
sum = sum + gradeArray[subscript];
}//end of for loop
30 of 3307/11/2016
//Determine the statistics
average = sum / SIZE;
//Clear the screen
system("cls");
/***** Sort the grades ****/
pairsToCompare = SIZE - 1;
y = 0;
while (y < SIZE)
{
x = 0;
while (x < pairsToCompare)
{
if (gradeArray[x] > gradeArray[x+1])
{
temp = gradeArray[x];
gradeArray[x] = gradeArray [x + 1];
gradeArray[x + 1] = temp;
}
x = x + 1; //Increment noting a comparison is made
} //End inner while loop
y = y + 1;
pairsToCompare = pairsToCompare - 1; //Decrement comparison
} //End outer while loop
//Assign min and max scores
minimum = gradeArray[0];
maximum = gradeArray[SIZE - 1];
//Display the grades and statistics back to the user
//Display header outside of the loop
cout << endl;
cout << "The sorted grades and statistics are:\n";
cout << "---------------------------------\n";
//Display and save the sorted array
for(int sub = 0; sub < SIZE; sub++)
{
cout << gradeArray[sub] << endl;
outFile << gradeArray[sub] << endl;
//to screen
//to file
} //end of for loop
//Display and save the
cout << "Average: " <<
cout << "Minimum: " <<
cout << "Maximum: " <<
average, minimum, and maximum grade
average << endl;
minimum << endl;
maximum << endl;
// Write data to the file
outFile << "Average: " << average << endl;
outFile << "Minimum: " << minimum << endl;
31 of 3307/11/2016
outFile << "Maximum: " << maximum << endl;
//Display footer
cout << "---------------------------------\n\n";
} //end of program
An Example from Ted Tucker
// example of sorting
#include <iostream>
using namespace std;
const int DECLARED_SIZE = 10;
int sample_array[DECLARED_SIZE] =
{123,345,654,612,709,100,90,900,781,200};
int index_of_smallest(const int a[], int start_index, int number_used)
{
int min = a[start_index], index_of_min = start_index;
for (int index = start_index + 1; index < number_used; index++)
if (a[index] < min)
{
min = a[index];
index_of_min = index;
}
return index_of_min;
}
void swap_values(int& v1, int& v2)
{
int temp;
temp = v1;
v1 = v2;
v2 = temp;
}
void sort(int a[], int number_used)
{
int index_of_next_smallest;
for (int index = 0; index < number_used - 1; index++)
{
index_of_next_smallest = index_of_smallest(a, index,
number_used);
swap_values(a[index], a[index_of_next_smallest]);
}
}
int main()
{
cout << "This program sorts numbers from lowest highest.\n";
32 of 3307/11/2016
int
number_used;
number_used = DECLARED_SIZE;
sort(sample_array, number_used);
for ( int index = 0; index < number_used; index++)
cout << sample_array[index] << " ";
cout << endl;
return 0;
}
33 of 3307/11/2016
Download