السلاسل - تابع الفصل السابع 2

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

Chapter 7

290

The resulting random number k is then used as an index to swap two cards. We go through the
for loop, swapping one card, whose index points to each card in 0-to-51 order, with another
card, whose index is the random number. When all 52 cards have been exchanged with a
random card, the deck is considered to be shuffled. This program could form the basis for a
card-playing program, but we’ll leave these details for you.
Arrays of objects are widely used in C++ programming. We’ll see other examples as we go along.

C-Strings
We noted at the beginning of this chapter that two kinds of strings are commonly used in C++:
C-strings and strings that are objects of the string class. In this section we’ll describe the first
kind, which fits the theme of the chapter in that C-strings are arrays of type char. We call these
strings C-strings, or C-style strings, because they were the only kind of strings available in the
C language (and in the early days of C++, for that matter). They may also be called char* strings,
because they can be represented as pointers to type char. (The * indicates a pointer, as we’ll
learn in Chapter 10.)
Although strings created with the string class, which we’ll examine in the next section, have
superseded C-strings in many situations, C-strings are still important for a variety of reasons.
First, they are used in many C library functions. Second, they will continue to appear in legacy
code for years to come. And third, for students of C++, C-strings are more primitive and
therefore easier to understand on a fundamental level.

C-String Variables
As with other data types, strings can be variables or constants. We’ll look at these two entities
before going on to examine more complex string operations. Here’s an example that defines a
single string variable. (In this section we’ll assume the word string refers to a C-string.) It asks
the user to enter a string, and places this string in the string variable. Then it displays the
string. Here’s the listing for STRINGIN:
// stringin.cpp
// simple string variable
#include <iostream>
using namespace std;

int main()
{
const int MAX = 80; //max characters in string
char str[MAX]; //string variable str
Arrays and Strings
291

cout << “Enter a string: “;


cin >> str; //put string in str
//display string from str
cout << “You entered: “ << str << endl;
return 0;
}

The definition of the string variable str looks like (and is) the definition of an array of type char:
char str[MAX];

We use the extraction operator >> to read a string from the keyboard and place it in the string 7
variable str. This operator knows how to deal with strings; it understands that they are arrays
of characters. If the user enters the string “Amanuensis” (one employed to copy manuscripts)

ARRAYS AND
STRINGS
in this program, the array str will look something like Figure 7.9.

FIGURE 7.9
String stored in string variable.

Each character occupies 1 byte of memory. An important aspect of C-strings is that they must
terminate with a byte containing 0. This is often represented by the character constant ‘\0’, which
is a character with an ASCII value of 0. This terminating zero is called the null character. When
the << operator displays the string, it displays characters until it encounters the null character.
Chapter 7
292

Avoiding Buffer Overflow


The STRINGIN program invites the user to type in a string. What happens if the user enters a
string that is longer than the array used to hold it? As we mentioned earlier, there is no built-in
mechanism in C++ to keep a program from inserting array elements outside an array. So an
overly enthusiastic typist could end up crashing the system.
However, it is possible to tell the >> operator to limit the number of characters it places in an
array. The SAFETYIN program demonstrates this approach.
// safetyin.cpp
// avoids buffer overflow with cin.width
#include <iostream>
#include <iomanip> //for setw
using namespace std;

int main()
{
const int MAX = 20; //max characters in string
char str[MAX]; //string variable str

cout << “\nEnter a string: “;


cin >> setw(MAX) >> str; //put string in str,
// no more than MAX chars
cout << “You entered: “ << str << endl;
return 0;
}

This program uses the setw manipulator to specify the maximum number of characters the
input buffer can accept. The user may type more characters, but the >> operator won’t insert
them into the array. Actually, one character fewer than the number specified is inserted, so
there is room in the buffer for the terminating null character. Thus, in SAFETYIN, a maximum of
19 characters are inserted.

String Constants
You can initialize a string to a constant value when you define it. Here’s an example, STRINIT,
that does just that (with the first line of a Shakespearean sonnet):
// strinit.cpp
// initialized string
#include <iostream>
using namespace std;

int main()
{
char str[] = “Farewell! thou art too dear for my possessing.”;
Arrays and Strings
293

cout << str << endl;


return 0;
}

Here the string constant is written as a normal English phrase, delimited by quotes. This may
seem surprising, since a string is an array of type char. In past examples you’ve seen arrays
initialized to a series of values delimited by braces and separated by commas. Why isn’t str
initialized the same way? In fact you could use such a sequence of character constants:
char str[] = { ‘F’, ‘a’, ‘r’, ‘e’, ‘w’, ‘e’, ‘l’, ‘l’, ‘!’,’ ‘, ‘t’, ‘h’,

and so on. Fortunately, the designers of C++ (and C) took pity on us and provided the shortcut 7
approach shown in STRINIT. The effect is the same: The characters are placed one after the

ARRAYS AND
other in the array. As with all C-strings, the last character is a null (zero).

STRINGS
Reading Embedded Blanks
If you tried the STRINGIN program with strings that contained more than one word, you may
have had an unpleasant surprise. Here’s an example:
Enter a string: Law is a bottomless pit.
You entered: Law

Where did the rest of the phrase (a quotation from the Scottish writer John Arbuthnot, 1667–
1735) go? It turns out that the extraction operator >> considers a space to be a terminating
character. Thus it will read strings consisting of a single word, but anything typed after a space
is thrown away.
To read text containing blanks we use another function, cin.get(). This syntax means a mem-
ber function get() of the stream class of which cin is an object. The following example,
BLANKSIN, shows how it’s used.

// blanksin.cpp
// reads string with embedded blanks
#include <iostream>
using namespace std;

int main()
{
const int MAX = 80; //max characters in string
char str[MAX]; //string variable str

cout << “\nEnter a string: “;


cin.get(str, MAX); //put string in str
cout << “You entered: “ << str << endl;
return 0;
}
Chapter 7
294

The first argument to cin::get() is the array address where the string being input will be
placed. The second argument specifies the maximum size of the array, thus automatically
avoiding buffer overrun.
Using this function, the input string is now stored in its entirety.
Enter a string: Law is a bottomless pit.
You entered: Law is a bottomless pit.

There’s a potential problem when you mix cin.get() with cin and the extraction operator
(>>). We’ll discuss the use of the ignore() member function of cin to solve this problem in
Chapter 12, “Streams and Files.”

Reading Multiple Lines


We may have solved the problem of reading strings with embedded blanks, but what about
strings with multiple lines? It turns out that the cin::get() function can take a third argument
to help out in this situation. This argument specifies the character that tells the function to stop
reading. The default value for this argument is the newline (‘\n’) character, but if you call the
function with some other character for this argument, the default will be overridden by the
specified character.
In the next example, LINESIN, we call the function with a dollar sign (‘$’) as the third argument:
// linesin.cpp
// reads multiple lines, terminates on ‘$’ character
#include <iostream>
using namespace std;

const int MAX = 2000; //max characters in string


char str[MAX]; //string variable str

int main()
{
cout << “\nEnter a string:\n”;
cin.get(str, MAX, ‘$’); //terminate with $
cout << “You entered:\n” << str << endl;
return 0;
}

Now you can type as many lines of input as you want. The function will continue to accept
characters until you enter the terminating character (or until you exceed the size of the array).
Remember, you must still press Enter after typing the ‘$’ character. Here’s a sample interac-
tion with a poem from Thomas Carew (1595–1639):
Arrays and Strings
295

Enter a string:
Ask me no more where Jove bestows
When June is past, the fading rose;
For in your beauty’s orient deep
These flowers, as in their causes, sleep.
$
You entered:
Ask me no more where Jove bestows
When June is past, the fading rose;
For in your beauty’s orient deep
These flowers, as in their causes, sleep.
7
We terminate each line with Enter, but the program continues to accept input until we

ARRAYS AND
enter ‘$’.

STRINGS
Copying a String the Hard Way
The best way to understand the true nature of strings is to deal with them character by
character. The following program does this.
// strcopy1.cpp
// copies a string using a for loop
#include <iostream>
#include <cstring> //for strlen()
using namespace std;

int main()
{ //initialized string
char str1[] = “Oh, Captain, my Captain! “
“our fearful trip is done”;

const int MAX = 80; //size of str2 buffer


char str2[MAX]; //empty string

for(int j=0; j<strlen(str1); j++) //copy strlen characters


str2[j] = str1[j]; // from str1 to str2
str2[j] = ‘\0’; //insert NULL at end
cout << str2 << endl; //display str2
return 0;
}

This program creates a string constant, str1, and a string variable, str2. It then uses a for
loop to copy the string constant to the string variable. The copying is done one character at a
time, in the statement
str2[j] = str1[j];

Recall that the compiler concatenates two adjacent string constants into a single one, which
allows us to write the quotation on two lines.
Chapter 7
296

This program also introduces C-string library functions. Because there are no string operators
built into C++, C-strings must usually be manipulated using library functions. Fortunately there
are many such functions. The one we use in this program, strlen(), finds the length of a C-
string (that is, how many characters are in it). We use this length as the limit in the for loop so
that the right number of characters will be copied. When string functions are used, the header
file CSTRING (or STRING.H) must be included (with #include) in the program.
The copied version of the string must be terminated with a null. However, the string length
returned by strlen() does not include the null. We could copy one additional character, but
it’s safer to insert the null explicitly. We do this with the line
str2[j] = ‘\0’;

If you don’t insert this character, you’ll find that the string printed by the program includes all
sorts of weird characters following the string you want. The << just keeps on printing characters,
whatever they are, until by chance it encounters a ‘\0’.

Copying a String the Easy Way


Of course, you don’t need to use a for loop to copy a string. As you might have guessed, a
library function will do it for you. Here’s a revised version of the program, STRCOPY2, that
uses the strcpy() function.
// strcopy2.cpp
// copies a string using strcpy() function
#include <iostream>
#include <cstring> //for strcpy()
using namespace std;

int main()
{
char str1[] = “Tiger, tiger, burning bright\n”
“In the forests of the night”;
const int MAX = 80; //size of str2 buffer
char str2[MAX]; //empty string

strcpy(str2, str1); //copy str1 to str2


cout << str2 << endl; //display str2
return 0;
}

Note that you call this function with the destination first:
strcpy(destination, source)

The right-to-left order is reminiscent of the format of normal assignment statements: The variable
on the right is copied to the variable on the left.
Arrays and Strings
297

Arrays of Strings
If there are arrays of arrays, of course there can be arrays of strings. This is actually quite a
useful construction. Here’s an example, STRARAY, that puts the names of the days of the week
in an array:
// straray.cpp
// array of strings
#include <iostream>
using namespace std;

int main() 7
{

ARRAYS AND
const int DAYS = 7; //number of strings in array

STRINGS
const int MAX = 10; //maximum size of each string
//array of strings
char star[DAYS][MAX] = { “Sunday”, “Monday”, “Tuesday”,
“Wednesday”, “Thursday”,
“Friday”, “Saturday” };
for(int j=0; j<DAYS; j++) //display every string
cout << star[j] << endl;
return 0;
}

The program prints out each string from the array:


Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

Since a string is an array, it must be true that star—an array of strings—is really a two-
dimensional array. The first dimension of this array, DAYS, tells how many strings are in the
array. The second dimension, MAX, specifies the maximum length of the strings (9 characters
for “Wednesday” plus the terminating null makes 10). Figure 7.10 shows how this looks.
Notice that some bytes are wasted following strings that are less than the maximum length.
We’ll learn how to remove this inefficiency when we talk about pointers.

You might also like