| I l @ ve RuBoard |
9.8 Programming ExercisesExercise 9-1: Write a procedure that counts the number of words in a string. (Your documentation should describe exactly how you define a word.) Write a program to test your new procedure. Exercise 9-2: Write a function begins(string1, string2) that returns true if string1 begins string2 . Write a program to test the function. Exercise 9-3: Write a function count(number, array, length) that will count the number of times number appears in array . The array has length elements. The function should be recursive. Write a test program to go with the function. Exercise 9-4: Write a function that will take a character string and return a primitive hash code by adding up the value of each character in the string.
Exercise 9-5:
Write a function that returns the maximum value of an array of
Exercise 9-6:
Write a function that
|
| I l @ ve RuBoard |
| I l @ ve RuBoard |
9.9 Answers to Chapter QuestionsAnswer 9-1: The programmer went to a lot of trouble to explain that the for loop did nothing (except increment the index). However, there is no semicolon at the end of the for . C++ keeps reading until it sees a statement (in this case return(index) ) and puts it in the for loop. Example 9-11 contains a correctly written version of the program. Example 9-11. length/rlen.cpp
int length(char string[])
{
int index; // index into the string
/*
* Loop until we reach the end of string character
*/
for (index = 0; string[index] != '
|
| I l @ ve RuBoard |
| I l @ ve RuBoard |
Chapter 10. The C++ Preprocessor
The first C compilers had no constants or inline functions. When C was still being developed, it soon became apparent that it needed a facility for handling named constants, macros, and include files. The solution was to create a preprocessor that is run on the programs before they are passed to the C compiler. The preprocessor is nothing more than a specialized text editor. Its syntax is completely different from C's, and it has no understanding of C constructs. It is merely a dumb text editor.
The preprocessor was soon merged into the main C compiler. The C++ compiler kept this preprocessor. On some systems, such as Unix, it is still a separate program, automatically executed by the compiler wrapper
cc.
Some of the
|
| I l @ ve RuBoard |
| I l @ ve RuBoard |
10.1 #define StatementThe #define statement can be used to define a constant. For example, the following two lines perform similar functions: #define SIZE 20 // The array size is 20 const int SIZE = 20; // The array size is 20 Actually the line #define SIZE 20 acts as a command to the preprocessor to globallychangeSIZEto20. This takes the drudgery and guesswork out of making changes.
All preprocessor commands begin with a hash mark (#) as the first character of the line. (You can put whitespace before the #, but this is rarely done.) C++ is
Preprocessor directives terminate at the end of the line. In C++ a semicolon (;) ends a statement. The preprocessor directives do not end in a semicolon, and
#define FOO bar
causes the preprocessor to replace the word "FOO" with the word "bar" everywhere "FOO" occurs. It is common programming practice to use all uppercase
The general form of a simple #define statement is: #define Name Substitute-Text
Name
can be any valid C++ identifier.
Substitute-Text
can be anything as long as it fits on a single line. The
Substitute-Text
can include spaces, operators, and other
Consider the following definition: #define FOR_ALL for (i = 0; i < ARRAY_SIZE; ++i) It is possible to use it like this:
/*
* Clear the array
*/
FOR_ALL {
data[i] = 0;
}
It is
It is even
#define BEGIN {
#define END }
. . .
if (index == 0)
BEGIN
std::cout << "Starting\n";
END
The problem is that you are no longer programming in C++, but in a half C++, half-PASCAL mongrel. The preprocessor can cause unexpected problems because it does not check for correct C++ syntax. For example, Example 10-1 generates an error on line 11. Example 10-1. big/big.cpp
1:#define BIG_NUMBER 10 ** 10
2:
3:int main( )
4:{
5: // index for our calculations
6: int index;
7:
8: index = 0;
9:
10: // syntax error on next line
11: while (index < BIG_NUMBER) {
12: index = index * 8;
13: }
14: return (0);
15:
The problem is in the #define statement on line 1, but the error message points to line 11. The definition in line 1 causes the preprocessor to expand line 11 to look like: while (index < 10 ** 10) Because ** is an illegal operator, this generates a syntax error. Question 10-1: The following program generates the answer 47 instead of the expected answer 144. Why? (Hint below.) Example 10-2. first/first.cpp
#include <iostream>
#define FIRST_PART 7
#define LAST_PART 5
#define ALL_PARTS FIRST_PART + LAST_PART
int main( ) {
std::cout << "The square of all the parts is " <<
ALL_PARTS * ALL_PARTS << '\n';
return (0);
}
Hint: CC -E prog.cc sends the output of the preprocessor to the standard output. In MS-DOS/Windows, the command: cpp prog.cpp creates a file called prog.i containing the output of the preprocessor. Running the program for Example 10-2 through the preprocessor gives you the code shown in Example 10-3. Example 10-3. first/first-ed.out
# 1 "first.cpp"
# 1 "/usr/local/lib/g++-include/iostream" 1 3
// About 900 lines of #include stuff omitted
inline ios& oct(ios& i)
{ i.setf(ios::oct, ios::decios::hexios::oct); return i; }
# 1 "first.cpp" 2
int main( ) {
std::cout << "The square of all the parts is " <<
7 + 5 * 7 + 5 << '\n';
return (0);
}
Question 10-2:
Example 10-4 generates a warning that
counter
is used before it is set. This is a surprise because the
for
loop should set it. You also get a very
Example 10-4. max/max.cpp
// warning, spacing is VERY important
#include <iostream>
#define MAX =10
int main( )
{
int counter;
for (counter =MAX; counter > 0; --counter)
std::cout << "Hi there\n";
return (0);
}
Hint : Take a look at the preprocessor output.
Question 10-3: Example 10-5 computes the wrong value for size . Why? Example 10-5. size/size.cpp
#include <iostream>
#define SIZE 10;
#define FUDGE SIZE -2;
int main( )
{
int size;// size to really use
size = FUDGE;
std::cout << "Size is " << size << '\n';
return (0);
}
Question 10-4: Example 10-6 is supposed to print the message Fatal Error: Abort and exit when it receives bad data. But when it gets good data, it exits. Why? Example 10-6. die/die.cpp
#include <iostream>
#include <cstdlib>
#define DIE \
std::cerr << "Fatal Error:Abort\n";exit(8);
int main( ) {
// a random value for testing
int value;
value = 1;
if (value < 0)
DIE;
std::cerr << "We did not die\n";
return (0);
}
10.1.1 #define Versus const
The
const
keyword is relatively new. Before
const
,
#define
was the only way to define constants, so most older code uses
#define
directives. However,the useof
const
is preferred over
#define
for several reasons. First, C++ checks the syntax of
const
statements immediately. The
#define
directive is not checked until the macro is used. Also,
const
uses C++ syntax, while
#define
has a syntax all its own. Finally,
const
In most cases a const statement is preferred over #define . Here are two ways of defining the same constant:
#define MAX 10 // Define a value using the pre-processor
// (This can easily cause problems)
const int MAX = 10; // Define a C++ constant integer
// (Safer)
The #define directive is limited to defining simple constants. The const statement can define almost any type of C++ constant, including things such as structure classes. For example:
struct box {
int width, height; // Dimensions of the box in pixels
};
// Size of a pink box to be used for input
const box pink_box(1, 4);
The #define directive is, however, essential for things such as conditional compilation and other specialized uses. |
| I l @ ve RuBoard |