Previous | Table of Contents | Next |
Parentheses help clarify the effect of the loop statement. Note that postfix increment ++ has a higher precedence than indirection (*). Because it is a postfix increment, the increment is applied after the rest of the statement is evaluated (so p++ is equivalent to p except for a side effect that is resolved later).
while (i++ < 1000) *(p++) = 100;
The loop could have been made even more self-evident, but less compact, by writing it this way:
while (i++ < 1000) { *p = 100; // Assign 100 to element pointed to p++; // Point to next element }
The first statement inside the loop (*p = 100) is an operation on the data pointed to. But the second statement (p++) is an operation on the pointer itself. Adding one to a pointer always advances it to point to the next element regardless of the size of the base type.
Figure 3.5 illustrates how this loop processes the array by assigning a value and then advancing to the next element.
Figure 3.5 Using a pointer for loop processing on an array.
Similar code can be used to copy all the members of one array, b, to all the members of another array, a:
int a[1000], b[1000]; ... int i = 0; int *pa = a; int *pb = b; while (i++ < 1000) *pa++ = *pb++;
Again, the precedence of postfix increment (++) is higher than that of indirection (*), so the loop has the same effect as the following, less compact version:
while (i++ < 1000) { *pa = *pb; // Copy element from b to a pa++; // Point to next element in a pb++; // Point to next element in b }
Figure 3.6 illustrates how this loop processes the array by assigning a value and then advancing to the next element.
Figure 3.6 Using pointers for loop processing on two arrays.
Array-handling techniques, especially those involving pointers, are useful in handling C++ character strings. If you are not well versed in how pointers can be used to process array elements, its a good idea to go back and review the preceding section.
In C++, a character string is an array of char. Technically, a char is an integer, one byte in length. (Note, however, that there is no necessary connection between strings and one byte; the wide-character format, used in products intended for international distribution, uses two bytes per character.) When printed on screen, each char value is mapped to a printable character. The mapping system most widely in use today is the ASCII coding convention.
Simply stated, a character string is implemented as an array of one-byte integers, in which each integer represents an ASCII character code.
![]() | If you are used to string handling in Basic, you may at first find that string handling is not as easy in C++. For example, you have to call a library function (strcpy) just to assign one string value to another. In Chapters 5, 6, and 7, I use object-oriented C++ features to create a string class every bit as easy to use as Basic strings. This class demonstrates much of the power of C++ object orientation. But to understand the code for Chapters 5, 6, and 7, its important to first understand the underlying mechanics of C++ strings. |
Incidentally, character strings are never simple valuesno matter what the language. A language such as Basic simply hides the underlying array-handling mechanics from you. C and C++ give you more control by not hiding whats going on. |
C++ strings have one special characteristic in addition to being arrays. This is the first cardinal rule of string handling: A string is terminated with a null byte (\0), which is a value of zero (as opposed to a printable character 0).
The location of the null-terminating byte determines the effective length of the string. This is a potential point of confusion for people who are new to C/C++ strings. You can allocate as many bytes for a string as you want, but the current length depends on the location of the first null byte. If you pass a string to the printf function, for example, only the characters up to the first null are printed; everything past that character is ignored. This can be stated as the second cardinal rule of string handling: The array dimension of a string determines its maximum length (minus one for the null terminator) and not its current length.
The following simple example should clarify. Suppose you declare a string as follows:
char str[10] = Hello
The name str is declared as a char array. It is therefore a string with maximum length of nine (10, minus one for the null-terminating byte). The declaration initializes the string with the value Hello, so it is represented in memory as shown in Figure 3.7.
Figure 3.7 A string with unused bytes.
The last four bytes are not currently in use. But they could be used if a new set of characters were to be copied into the string (by using the strcpy function, as youll see later). In no case, however, should more than 10 bytes be copied to this string location. Doing so would overwrite data areas reserved for other variables or even other programs. This is another way in which C++ differs from a language such as Basic. You need to pay attention to the maximum lengths you have set.
By the way, an alternative way to create a string is to omit an explicit array dimension. In that case, C++ allocates just enough bytes to store the initial string, and no more. This approach is fine as long as the string will never grow in length.
char str[] = Hello;
Figure 3.8 shows the resulting byte layout in memory.
Figure 3.8 A string with no unused bytes.
When creating C++ strings, you can initialize them with any string constant, as was done in the last two examples. Note that this use of the equal sign (=) is initialization and not assignment; it is limited to the same statement that declares and defines the string.
But after a string is declared, you must use the strcpy function to copy a new string value (or write a strcpy function yourself, which is easy). You cant simply assign one string to another as if they were numbers or simple objects. This can be stated as the third cardinal rule of C++ string handling: Because strings are arrays, they cant be directly assigned to each other. You must call a function or use a loop to copy one character at a time.
This is where string handling in C++ seems more difficult than in other languages. You cant write statements such as A$ = B$ as you can in Basic. The following code produces an error:
char string1[10] = One; char string2[10] = Two; string2 = string1; // ERROR! Cannot assign to // string
Your compiler would probably give you an unhelpful, unfriendly message such as Cannot assign to a constant,. although this message makes sense when you consider that C++ array names are actually constants that translate into the address of the first element.
To copy the contents of one string to another, use the strcpy function:
#include <string.h> char string1[10] = One; char string2[10] = Two; strcpy (string2, string1); // Correct way to copy // string
Note the use of the #include directive to support the strcpy function, which requires the declaration in STRING.H. Include this file whenever you use any string-handling functions from the C++ standard library. Other string-handling functions are shown in Table 3.1.
Table 3.1 C++ string-handling functions. | |
Function | Description |
---|---|
strlen(char *s) | Return the number of characters up to, but not including, the first null byte. |
strncpy(char dest, char *src, int n) | Copy at most n characters. |
strcat(char *dest, char *src) | Concatenate contents of src onto the end of dest. |
The following code uses the strcpy and strcat functions from the standard library:
#include <stdio.h> #include <string.h> ... char *name[81]; // Max. length is 80 characters, //plus one for the null strcpy (name, Archie); strcat (name, ); strcat (name, Leach); printf (%s, he my friend.\n, name);
The %s format character specifies that the corresponding argument is the address of a string. Remember that an array name (in this case, an array of characters) translates into the starting address. This code prints the following string:
Archie Leach, he my friend.
Previous | Table of Contents | Next |