Some C++ Programming Examples to help you out.
C++ First Example
Throughout this book, code examples explain and illustrate important programming
and object oriented program (OOP) issues. The aim in each case is to use a minimal
example to illustrate the ideas and techniques briefly and efficiently. Example 1.1 provides
a quick overview of some elementary C++ syntax.
EXAMPLE 1.1
/* Computes and prints n! for a given n.
Uses several basic elements of C++. */
#include <iostream>
int main() {
using namespace std;
// Declarations of variables
int factArg = 0 ;
int fact(1) ;
do {
cout << "Factorial of: ";
cin >> factArg;
if ( factArg < 0 ) {
cout << "No negative values, please!" << endl;
}
} while (factArg < 0) ;
int i = 2;
while ( i <= factArg ) {
fact = fact * i;
i = i + 1;
}
cout << "The Factorial of " << factArg << " is: " << fact << endl;
return 0;
}
On most platforms, you can compile and run this program using the ubiquitous
GNU C compiler, gcc . The command to compile a C++ program is g++ , which is a
program that calls gcc , treats .c and .h files as C++ source files and automatically links
to the C++ library.
To maximize the amount of diagnostic information available from the compilation
process, use the command-line option, -Wall .
-Wall enables all possible warnings about constructions that might be considered
questionable even if they conform to the standard.
In the second version, the optional switch argument -o execFile is used to specify
the name of the generated executable. If you omit that option, as in the first version,
the compiler produces an executable file named a.out . 4 In either case, if there already
exists a file in the same directory with the name of your target executable (e.g., if you
are recompiling), the compiler quietly and automatically overwrites it.
These are just two of the most commonly used compiler options. On a *nix system,
you can view the manual page , a summary of command options and how they
are used, by typing the command
man g++
or
info g++
On most systems this command enables you to browse the online documentation
for g++ one screen at a time. For more complete gcc documentation, visit the GNU
online document center. 5
After it has been compiled successfully, the program can be run by typing the name
of the executable file. Here is an example on a *nix platform:
This short program uses several of the language elements that show up in most C++
programs.
Comments
C++ has single-line comments as in Java. Any text between // and the end of the line
is a comment. C-style comment-delimiters for multiline comments can also be used.
The text bet wee n /* and */ is a comment.
#include
To reuse functions, types, or identifiers from libraries, use the preprocessor directive
#include.6 As in C, all preprocessor directives begin with the pound sign character
# and are evaluated just before the compiler compiles your code. In this example,
the included header <iostream> contains the Standard Library definitions for input/
output.
using namespace
Symbols from the Standard Library ( Appendix B , “Standard Headers”) are enclosed in
the namespace std .
A namespace is a collection of classes, functions, and objects that
can be addressed with a named prefix. The using declaration tells the compiler to add
all symbols from the specified namespace ( std ) into the global namespace.
Declaring and Initializing Variables
Variable declarations come in three styles in C++ :
type-expr variableName;
type-expr variableName = init-expr;
type-expr variableName ( init-expr);
In the first form, the variable might not be initialized. Th e third form is an alternative
syntax for the second.
Selection
C++ provides the usual assortment of syntax variations for selection and control structures,
Iteration
Example 1.1 uses two of the three iteration structures provided by C++. Section 19.2.3
discusses all three.
Standard Input and Output
In Example 1.1 , the directive
#include <iostream>
enabled you to use predefined global input (istream) and output (ostream) objects.
1. cin , console input , the keyboard by default.
2. cout , console output , the console screen by default.
3. cerr , console error , another output stream to the console screen that flushes
more often and is normally used for error messages.
In Example, we used the global ostream object, cout . We also called one of its
member functions, operator<<() . This function overloads the << operator and is used
to insert data into the output stream, so we call it the insertion operator. 7 The syntax
for that output statement is also quite interesting. Instead of using the rather bulky
function notation
cout.operator<<("Factorial of: ");
we invoked the same function using the more elegant and readable infix syntax:
cout << "Factorial of: ";
This operator can be c hained (used on multiple values) and is predefined for use
with many built-in types, as you see in the next output statement.
cout << "The cost is $" << 23.45 << " for " << 6 << " items." << '\n';
In Example, you can see the operator>>() used for input with the istream
object cin in an analogous way to the way we used << for output with the ostream
object cout . Because the effect of this operator is to extract data from the input stream,
we call it the extraction operator.
EXAMPLE 1.2
#include <string>
#include <iostream>
int main() {
using namespace std;
const int THISYEAR = 2011;
string yourName;
int birthYear;
cout << "What is your name? " << flush;
cin >> yourName;
cout << "What year were you born? " ;
cin >> birthYear;
cout << "Your name is " << yourName
<< " and you are approximately "
<< (THISYEAR - birthYear)
<< " years old. " << endl;
The symbols flush and endl are manipulators from the std namespace.
In Example 1.2 , we use the string class, 10 also from the C++ Standard Library. We
discuss this type and demonstrate some of its functions later
NOTE
For Windows/MSVC Users
By default, MSVC generates applications with no console support. This means that you cannot
use the standard i/o/error streams unless you tell MSVC to build a console application. See the
note “ CONFIG += console (for MSVC Users) ”.
Standard Input and Output
1. In the [dist] directory, we have provided a tarball named src.tar.gz that contains
Using Example 1.2 , do the following experiments:
using namespace std;
• Replace the statement
cin >> yourName;
with the statement
getline(cin, yourName);
and try Curious George again.
• Can you explain the differences in behavior between cin >> and getline() ?
We discuss this in Section 1.8 .
• Add some more questions to the program that require a variety of numerical
and string answers and test the results.
Introduction to Functions
Every modern programming language has a way for programmers to define functions.
Functions enable you to divide a program into manageable components instead of
presenting it as a large, complex monolith. This enables you to develop and test small
components individually or in small groups and makes it easier to build and maintain
software. Functions also provide a way to write reusable code for specific tasks. For
example, Example 1.1 computes the factorial of a given number inside the main() function.
Example 1.3 shows how to extract the code for computing factorials and
transform it into a reusable function.
EXAMPLE 1.3
#include <iostream>
long factorial(long n) {
long ans = 1;
for (long i = 2; i <= n; ++i) {
ans = ans * i;
if (ans < 0) {
return -1;
}
}
return ans;
}
int main() {
using namespace std;
cout << "Please enter n: " << flush;
long n; 1
cin >> n; 2
if (n >= 0) {
long nfact = factorial(n);
if (nfact < 0) {
cerr << "overflow error: "
<< n << " is too big." << endl;
}
else {
cout << "factorial(" << n << ") = "
<< nfact << endl;
}
}
else {
cerr << "Undefined: "
<< "factorial of a negative number: " << n << endl;
}
return 0;
}
With the exception of constructors and destructors,11 discussed in Chapter 2, and
conversion operators, discussed in Section 19.9.1, every function must have
• A return type (which may be void )
• A name
• An ordered, comma-separated list (which may be empty) of the types of the
function’s parameters
• A body (a block of zero or more statements enclosed in {braces})
The first three are the function’s interface, and the last is its implementation.
In Example 1.3 , the function definition appears above the statement that invokes it;
however, it may not always be possible or desirable to place a function definition before
every instance in which it is called. C and C++ allow a function to be called before it
has been defined, as long as the function has been declared prior to the call.
The mechanism for declaring a function (i.e., describing to the compiler how it is
to be invoked) is the function prototype . A function prototype includes the following
information:
• Function’s return type
• Function’s name
• Function’s parameter list
In other words, it includes everything except the function’s body. Here are a few
prototypes.
int toCelsius(int fahrenheitValue);
QString toString();
double grossPay(double hourlyWage, double hoursWorked);
Remember, a function must be declared or defined before it is used for the first
time so that the compiler can set up calls to it properly. We discuss declarations and
definitions in more detail in Section 20.1. It is an error to omit the return type (even if it is void ) except for the main() function, in which case the return type implicitly
defaults to int .
Although parameter names are optional in function prototypes, it is good programming
practice to use them. They constitute an effective and efficient part of the documentation
for a program.
A simple example can help to show why parameter names should be used in function
prototypes. Suppose you needed a function to set a Date with values for the year,
month, and day. If you presented the prototype as setDate(int, int, int) , the
programmer working with Dates would not know immediately from the prototype
alone in what order to list the three values when calling that function. Because at least
three of the possible orderings are in common use somewhere on the planet, there is
no “obvious” answer that would eliminate the need for more information. As you can
see in Section 2.2, the definition of a member function is usually kept in a separate file
from the declaration (and might not be accessible), so a programmer might have some
difficulty figuring out how to call the function. By giving the parameters good names,
that problem is eliminated and the function has, at least partially, documented itself.
Function Overloading
C++ permits overloading of function names. This enables programmers to attach the
same function name to different implementations with different parameters.
The signature of a function consists of its name and its parameter list. In C++, the
return type is not part of the signature.
A function name is overloaded if two or more functions within a given scope have
the same name but different signatures . It is an error to have two functions in the same
scope with the same signature but different return types. Overloading requires the
compiler to determine, by analyzing the argument list, which version of an overloaded
function gets executed in response to a function call. Because the decision is entirely
based upon the argument list, it is easy to see why the compiler cannot permit functions
with the same signature but different return types to coexist in the same scope.
We discuss that decision process in Section 5.1. In the meantime, Example 1.4 provides
some function calls to ponder.
EXAMPLE 1.4
#include <iostream>
using namespace std;
void foo(int n) {
cout << n << " is a nice number." << endl;
}
int main() {
cout << "before call: " << 5 << endl;
foo(5);
cout << "before call: " << 6.7 << endl;
foo(6.7);
cout << "before call: " << true << endl;
foo(true);
}
Here there is only one function, but we call it with three different numerical types.
In this case, automatic type conversions permit the function to be called three times.
src/functions> g++ overload-not.cpp
src/functions> ./a.out
before call: 5
5 is a nice number.
before call: 6.7
6 is a nice number.
before call: 1
1 is a nice number.
src/functions>
This output shows some of the harsh realities of numerical types. First, when a
floating point number gets converted to an int , its fractional part (the decimal point
and all digits to the right of it) is discarded. Even though 6.7 is closer to 7 than to 6,
no rounding takes place. Second, the bool value true is displayed as 1 (and false is
displayed as 0 ). If you want to see the word true (or false ), you need to add code to
output the appropriate strings as shown in Example 1.5 .
C++ First Example
Throughout this book, code examples explain and illustrate important programming
and object oriented program (OOP) issues. The aim in each case is to use a minimal
example to illustrate the ideas and techniques briefly and efficiently. Example 1.1 provides
a quick overview of some elementary C++ syntax.
EXAMPLE 1.1
/* Computes and prints n! for a given n.
Uses several basic elements of C++. */
#include <iostream>
int main() {
using namespace std;
// Declarations of variables
int factArg = 0 ;
int fact(1) ;
do {
cout << "Factorial of: ";
cin >> factArg;
if ( factArg < 0 ) {
cout << "No negative values, please!" << endl;
}
} while (factArg < 0) ;
int i = 2;
while ( i <= factArg ) {
fact = fact * i;
i = i + 1;
}
cout << "The Factorial of " << factArg << " is: " << fact << endl;
return 0;
}
- Standard C++ library—In older versions of C++, you might find <iostream.h> instead, but that version is regarded as “deprecated”; i.e., its use is discouraged.
- Start of function main, which returns an int
- Permits you to use the symbols cin, cout, and endl without prefixing each name with std::
- C-style initialization syntax
- C++ style initialization syntax
- Start of do..while loop
- Write to standard output
- Read from standard input and convert to int
- End of if block
- If false, break out of do loop
- Start of while loop
- End of while block
- When main returns 0, that normally means “no errors”
- End of main block
On most platforms, you can compile and run this program using the ubiquitous
GNU C compiler, gcc . The command to compile a C++ program is g++ , which is a
program that calls gcc , treats .c and .h files as C++ source files and automatically links
to the C++ library.
To maximize the amount of diagnostic information available from the compilation
process, use the command-line option, -Wall .
-Wall enables all possible warnings about constructions that might be considered
questionable even if they conform to the standard.
In the second version, the optional switch argument -o execFile is used to specify
the name of the generated executable. If you omit that option, as in the first version,
the compiler produces an executable file named a.out . 4 In either case, if there already
exists a file in the same directory with the name of your target executable (e.g., if you
are recompiling), the compiler quietly and automatically overwrites it.
These are just two of the most commonly used compiler options. On a *nix system,
you can view the manual page , a summary of command options and how they
are used, by typing the command
man g++
or
info g++
On most systems this command enables you to browse the online documentation
for g++ one screen at a time. For more complete gcc documentation, visit the GNU
online document center. 5
After it has been compiled successfully, the program can be run by typing the name
of the executable file. Here is an example on a *nix platform:
This short program uses several of the language elements that show up in most C++
programs.
Comments
C++ has single-line comments as in Java. Any text between // and the end of the line
is a comment. C-style comment-delimiters for multiline comments can also be used.
The text bet wee n /* and */ is a comment.
#include
To reuse functions, types, or identifiers from libraries, use the preprocessor directive
#include.6 As in C, all preprocessor directives begin with the pound sign character
# and are evaluated just before the compiler compiles your code. In this example,
the included header <iostream> contains the Standard Library definitions for input/
output.
using namespace
Symbols from the Standard Library ( Appendix B , “Standard Headers”) are enclosed in
the namespace std .
A namespace is a collection of classes, functions, and objects that
can be addressed with a named prefix. The using declaration tells the compiler to add
all symbols from the specified namespace ( std ) into the global namespace.
Declaring and Initializing Variables
Variable declarations come in three styles in C++ :
type-expr variableName;
type-expr variableName = init-expr;
type-expr variableName ( init-expr);
In the first form, the variable might not be initialized. Th e third form is an alternative
syntax for the second.
Selection
C++ provides the usual assortment of syntax variations for selection and control structures,
Iteration
Example 1.1 uses two of the three iteration structures provided by C++. Section 19.2.3
discusses all three.
Standard Input and Output
In Example 1.1 , the directive
#include <iostream>
enabled you to use predefined global input (istream) and output (ostream) objects.
1. cin , console input , the keyboard by default.
2. cout , console output , the console screen by default.
3. cerr , console error , another output stream to the console screen that flushes
more often and is normally used for error messages.
In Example, we used the global ostream object, cout . We also called one of its
member functions, operator<<() . This function overloads the << operator and is used
to insert data into the output stream, so we call it the insertion operator. 7 The syntax
for that output statement is also quite interesting. Instead of using the rather bulky
function notation
cout.operator<<("Factorial of: ");
we invoked the same function using the more elegant and readable infix syntax:
cout << "Factorial of: ";
This operator can be c hained (used on multiple values) and is predefined for use
with many built-in types, as you see in the next output statement.
cout << "The cost is $" << 23.45 << " for " << 6 << " items." << '\n';
In Example, you can see the operator>>() used for input with the istream
object cin in an analogous way to the way we used << for output with the ostream
object cout . Because the effect of this operator is to extract data from the input stream,
we call it the extraction operator.
EXAMPLE 1.2
#include <string>
#include <iostream>
int main() {
using namespace std;
const int THISYEAR = 2011;
string yourName;
int birthYear;
cout << "What is your name? " << flush;
cin >> yourName;
cout << "What year were you born? " ;
cin >> birthYear;
cout << "Your name is " << yourName
<< " and you are approximately "
<< (THISYEAR - birthYear)
<< " years old. " << endl;
The symbols flush and endl are manipulators from the std namespace.
In Example 1.2 , we use the string class, 10 also from the C++ Standard Library. We
discuss this type and demonstrate some of its functions later
NOTE
For Windows/MSVC Users
By default, MSVC generates applications with no console support. This means that you cannot
use the standard i/o/error streams unless you tell MSVC to build a console application. See the
note “ CONFIG += console (for MSVC Users) ”.
Standard Input and Output
1. In the [dist] directory, we have provided a tarball named src.tar.gz that contains
all the code examples in this book. An extremely valuable practice that
you should adopt is to take each code example, build and run it to see how it is
supposed to behave, and then break it by making various changes to see what
happens. Sometimes you can learn how the compiler responds to a particular syntax
error that your change produced. The compiler can be your best friend
if you can learn to understand its language. Other times you can see how the
runtime behavior of the program is affected by a particular logic error that you
produced. In each case, the experience can strengthen your understanding of
C++ programming.
Using Example 1.2 , do the following experiments:
• First, compile and run it, to see its normal behavior.
• What happens if you enter a non-numeric value for the birth year?
• What happens if you enter a name like Curious George as your name?
• What happens if you remove the following line?
using namespace std;• Replace the statement
cin >> yourName;
with the statement
getline(cin, yourName);
and try Curious George again.
• Can you explain the differences in behavior between cin >> and getline() ?
We discuss this in Section 1.8 .
• Add some more questions to the program that require a variety of numerical
and string answers and test the results.
Introduction to Functions
Every modern programming language has a way for programmers to define functions.
Functions enable you to divide a program into manageable components instead of
presenting it as a large, complex monolith. This enables you to develop and test small
components individually or in small groups and makes it easier to build and maintain
software. Functions also provide a way to write reusable code for specific tasks. For
example, Example 1.1 computes the factorial of a given number inside the main() function.
Example 1.3 shows how to extract the code for computing factorials and
transform it into a reusable function.
EXAMPLE 1.3
#include <iostream>
long factorial(long n) {
long ans = 1;
for (long i = 2; i <= n; ++i) {
ans = ans * i;
if (ans < 0) {
return -1;
}
}
return ans;
}
int main() {
using namespace std;
cout << "Please enter n: " << flush;
long n; 1
cin >> n; 2
if (n >= 0) {
long nfact = factorial(n);
if (nfact < 0) {
cerr << "overflow error: "
<< n << " is too big." << endl;
}
else {
cout << "factorial(" << n << ") = "
<< nfact << endl;
}
}
else {
cerr << "Undefined: "
<< "factorial of a negative number: " << n << endl;
}
return 0;
}
With the exception of constructors and destructors,11 discussed in Chapter 2, and
conversion operators, discussed in Section 19.9.1, every function must have
• A return type (which may be void )
• A name
• An ordered, comma-separated list (which may be empty) of the types of the
function’s parameters
• A body (a block of zero or more statements enclosed in {braces})
The first three are the function’s interface, and the last is its implementation.
In Example 1.3 , the function definition appears above the statement that invokes it;
however, it may not always be possible or desirable to place a function definition before
every instance in which it is called. C and C++ allow a function to be called before it
has been defined, as long as the function has been declared prior to the call.
The mechanism for declaring a function (i.e., describing to the compiler how it is
to be invoked) is the function prototype . A function prototype includes the following
information:
• Function’s return type
• Function’s name
• Function’s parameter list
In other words, it includes everything except the function’s body. Here are a few
prototypes.
int toCelsius(int fahrenheitValue);
QString toString();
double grossPay(double hourlyWage, double hoursWorked);
Remember, a function must be declared or defined before it is used for the first
time so that the compiler can set up calls to it properly. We discuss declarations and
definitions in more detail in Section 20.1. It is an error to omit the return type (even if it is void ) except for the main() function, in which case the return type implicitly
defaults to int .
Although parameter names are optional in function prototypes, it is good programming
practice to use them. They constitute an effective and efficient part of the documentation
for a program.
A simple example can help to show why parameter names should be used in function
prototypes. Suppose you needed a function to set a Date with values for the year,
month, and day. If you presented the prototype as setDate(int, int, int) , the
programmer working with Dates would not know immediately from the prototype
alone in what order to list the three values when calling that function. Because at least
three of the possible orderings are in common use somewhere on the planet, there is
no “obvious” answer that would eliminate the need for more information. As you can
see in Section 2.2, the definition of a member function is usually kept in a separate file
from the declaration (and might not be accessible), so a programmer might have some
difficulty figuring out how to call the function. By giving the parameters good names,
that problem is eliminated and the function has, at least partially, documented itself.
Function Overloading
C++ permits overloading of function names. This enables programmers to attach the
same function name to different implementations with different parameters.
The signature of a function consists of its name and its parameter list. In C++, the
return type is not part of the signature.
A function name is overloaded if two or more functions within a given scope have
the same name but different signatures . It is an error to have two functions in the same
scope with the same signature but different return types. Overloading requires the
compiler to determine, by analyzing the argument list, which version of an overloaded
function gets executed in response to a function call. Because the decision is entirely
based upon the argument list, it is easy to see why the compiler cannot permit functions
with the same signature but different return types to coexist in the same scope.
We discuss that decision process in Section 5.1. In the meantime, Example 1.4 provides
some function calls to ponder.
EXAMPLE 1.4
#include <iostream>
using namespace std;
void foo(int n) {
cout << n << " is a nice number." << endl;
}
int main() {
cout << "before call: " << 5 << endl;
foo(5);
cout << "before call: " << 6.7 << endl;
foo(6.7);
cout << "before call: " << true << endl;
foo(true);
}
Here there is only one function, but we call it with three different numerical types.
In this case, automatic type conversions permit the function to be called three times.
src/functions> g++ overload-not.cpp
src/functions> ./a.out
before call: 5
5 is a nice number.
before call: 6.7
6 is a nice number.
before call: 1
1 is a nice number.
src/functions>
This output shows some of the harsh realities of numerical types. First, when a
floating point number gets converted to an int , its fractional part (the decimal point
and all digits to the right of it) is discarded. Even though 6.7 is closer to 7 than to 6,
no rounding takes place. Second, the bool value true is displayed as 1 (and false is
displayed as 0 ). If you want to see the word true (or false ), you need to add code to
output the appropriate strings as shown in Example 1.5 .
No comments:
Post a Comment