# 9.8 Programming Exercises

 I l @ ve RuBoard

### 9.8 Programming Exercises

Exercise 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 numbers .

Exercise 9-6: Write a function that scans a string for the character "-" and replaces it with "_".

 I l @ ve RuBoard
 I l @ ve RuBoard

### 9.9 Answers to Chapter Questions

Answer 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] != '
int length(char string[]) { int index; // index into the string /* * Loop until we reach the end of string character */ for (index = 0; string[index] != '\0'; ++index) /* do nothing */ ; return (index); }

'; ++index)
/* do nothing */ ;
return (index);
}
```
 I l @ ve RuBoard
 I l @ ve RuBoard

## Chapter 10. The C++ Preprocessor

The speech of man is like embroidered tapestries, since like them this has to be extended in order to display its patterns, but when it is rolled up it conceals and distorts them.

”Themistocles

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 newer compilers, such as Borland-C++ Builder, have the preprocessor built in.

 I l @ ve RuBoard
 I l @ ve RuBoard

### 10.1 #define Statement

The #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 free-format . Language elements can be placed anywhere on a line, and the end-of-line is treated just like a space. The preprocessor is not free-format. It depends on the hash mark (#) being the first character on the line. As you will see, the preprocessor knows nothing about C++ and can be (and is) used to edit things other than C++ programs.

 The preprocessor is not part of the core C++ compiler. It uses an entirely different syntax and requires an entirely different mindset to use it well. Most problems you will see occur when the preprocessor is treated like C++.

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 putting one in can lead to unexpected results. A preprocessor directive can be continued by putting a backslash (\) at the end of the line. The simplest use of the preprocessor is to define a replacement macro. For example, the command:

```#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 letters for macro names . This makes it very easy to tell the difference between a variable (all lowercase) and a macro (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 characters .

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 considered bad programming practice to define macros in this manner. Doing so tends to obscure the basic control flow of the program. In this example, if the programmer wants to know what the loop does, he must search the beginning of the program for the definition of FOR_ALL .

It is even worse to define macros that do large-scale replacement of basic C++ programming constructs. For example, you can define the following:

```#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);
}
```
 The output of the C++ preprocessor contains a lot of information, most of which can easily be ignored. In this case, you need to scan the output until you reach the std::cout line. Examining this line will give you an idea of what caused the error.

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 strange warning, "null effect," for line 11. What's going on?

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

 Some preprocessors, such as the one that comes with the g++ compiler, add spaces around the tokens, which makes this program fail with a syntax error instead of compiling and generating strange code.
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

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 follows normal C++ scope rules, whereas constantsdefined by a #define directive continue on forever.

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