Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 7: Storing Sequences in Arrays 103

The choice of ‘\0’ as the terminating character was not random. Remember that zero is the only numeric value that converts to false; all other values translate to true. This means that the for loop could (and usually is) writ­ ten as:

for(int i = 0; stringArray[i]; i++)

This whole business of null terminated character strings is so ingrained into the C++ language psyche that C++ uses a string of characters surrounded by double quotes to be an array of characters automatically terminated with a ‘\0’ character. The following are identical declarations:

char szMyName[] = “Stephen”; char szAlsoMyName[] =

{‘S’, ‘t’, ‘e’, ‘p’, ‘h’, ‘e’, ‘n’, ‘\0’};

The naming convention used here is exactly that, a convention. C++ does not care. The prefix sz stands for zero-terminated string.

The string Stephen is eight characters long and not seven — the null charac­ ter after the n is assumed. The string “” is one character long consisting of just the null character.

Manipulating Strings with Character

The C++ programmer is often required to manipulate strings. C++ provides a number of standard string-manipulation functions to make the job easier. A few of these functions are listed in Table 7-1.

Table 7-1

String-Handling Functions

Name

 

Operation

int strlen(string)

 

Returns the number of characters

 

 

in a string.

void strcpy(target, source, n)

Copies the source string into a

 

 

target array.

 

 

void strcat(target, source, n)

Concatenates the source string

 

 

onto the end of the target string.

 

 

void strncpy(target, source, n)

Copies a string up to n characters

 

 

from the source string into a target

 

 

array.

 

 

 

(continued)

104 Part II: Becoming a Functional C++ Programmer

Table 7-1 (continued)

Name

Operation

void strncat(target, source, n)

Concatenates the source string

 

onto the end of the target string or

 

‘n’ characters, whichever comes

 

first.

 

 

int strnstr(string, pattern, n)

Finds the first occurrence of one

 

pattern string in another.

int strncmp(source1, source2, n)

Compares the first n characters in

 

two strings. Returns a zero if the

 

two strings match exactly.

 

 

int strnicmp(source1, source2)

Compares up to n characters in

 

two strings without regard to

 

case.

 

 

You need to add the statement #include <strings.h> to the beginning of any program that uses a str... function.

The current ANSI C++ standard suggests that you avoid the str...() func­ tions. ANSI C++ says that these functions are deprecated, meaning that ANSI will leave them alone for now, but don’t be surprised if they go away some day. That’s why strings.h uses the older standard of ending all include files with a “.h”. The ANSI standard suggests that you use the string type as defined in the next section. However, you will see a large number of programs that continue to use these functions.

The following Concatenate program inputs two strings from the keyboard and concatenates them into a single string.

// Concatenate - concatenate two strings // with a “ - “ in the middle #include <cstdio>

#include <cstdlib> #include <iostream> using namespace std;

//the following include file is deprecated;

//however, it is required for the str functions #include <strings.h>

int main(int nNumberofArgs, char* pszArgs[])

{

// read first string...

char szString1[256];

cout << “Enter string #1:”; cin >> szString1;

Chapter 7: Storing Sequences in Arrays 105

//safer alternative

//cin.getline(szString1, 128);

//...now the second string...

char szString2[128];

cout << “Enter string #2:”; cin >> szString2;

//safer alternative

//cin.getline(szString1, 128);

//accumulate both strings into a single buffer char szString[260];

//copy the first string into the buffer...

strncpy(szString, szString1, 128);

//...concatenate a “ - “ onto the first...

strncat(szString, “ - “, 4);

//...now add the second string...

strncat(szString, szString2, 128);

//...and display the result

cout << “\n” << szString << endl;

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

The Concatenate program reads two character strings and appends them together with a - in the middle.

The arguments to the str...() functions appear backward to any reason­ able individual (you might consider this an acid test for “reasonable”). For example, the function strncat(target, source, count) tacks the second string source onto the end of the first argument target.

An example output from the program appears as follows:

Enter string #1:Chester

Enter string #2:Dog

Chester - Dog

Press any key to continue . . .

The program begins by reading a string from the keyboard. cin >> szString1 stops when any type of whitespace is encountered. Characters up to the first whitespace are read, the whitespace character is tossed, and

106 Part II: Becoming a Functional C++ Programmer

the remaining characters are left in the input hopper for the next cin>> statement. Thus, if I were to enter “the Dog”, szString2 would be filled with “the”, and the word “Dog” would be left in the input buffer.

The cin >> extractor knows nothing about the length of the string. cin is perfectly willing to read thousands of characters and stuff them into szString1, even though it is declared 256 characters long. This causes a dangerous overflow condition that hackers can (and will) exploit to put a virus in your program.

C++ provides work-arounds for many of the string overflow problems. For example, the function getline() inputs a line of text; however, this function accepts the length of the string as one of its arguments:

cin.getline(string, lengthOfTheString);

(Ignore the strange looking cin. format for now.)

The strncpy() and strncat() functions accept the length of the target buffer as one of their arguments. The call strncpy(szString, szString1, 128) says “copy the characters in szString1 into szString until you copy a null character or until you’ve copied 128 characters, whichever comes first.” The call specifically does not mean copy 128 characters every time.

There are both “counting” and “noncounting” versions of most of the str...() functions. The noncounting versions don’t require the maximum number of characters to process as an argument. You can use these when you don’t know the buffer size, but be aware that they are perfectly happy to write beyond the end of the target string.

String-ing Along Variables

ANSI C++ includes a type string designed to make it easier to manipulate strings of text.

I use the term string to refer to an array of characters terminated by a null and string type to refer to the type string. The string type includes opera­ tions for copying, concatenating, capitalizing, knotting, and simple magic tricks. string avoids the overrun problems inherent with null terminated strings. The functions that manipulate string objects are defined in the include file <string>.

The string type based StringConcatenate program appears as follows:

Chapter 7: Storing Sequences in Arrays 107

// StringConcatenate - concatenate two string type // variables with a “ - “ in the middle #include <cstdio>

#include <cstdlib> #include <iostream> #include <string> using namespace std;

int main(int nNumberofArgs, char* pszArgs[])

{

//read first string...

string string1;

cout << “Enter string #1:”; cin >> string1;

//...now the second string...

string string2;

cout << “Enter string #2:”; cin >> string2;

//accumulate both strings into a single buffer string buffer;

string divider = “ - “;

buffer = string1 + divider + string2;

//...and display the result

cout << “\n” << buffer << endl;

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

This concatenate function defines two variables, string1 and string2 (clever, no?). A string type variable is not defined of any specified length — it can grow and shrink to fit the number of characters it contains (up to avail­ able memory, of course, or the cows come home, whichever is first). Not only do you not have to guess how big to make a target character array, but some nefarious user can’t crash your program by inputting too many characters. The StringConcatenate program manipulates the string type variables as it would any other.

Notice that some operations have to be understood in a slightly different way from their arithmetic equivalent. For example, to add two string type vari­ ables together means to concatenate them. In addition, notice how C++ can convert a null terminated character string into a string type variable with­ out being told to.

108 Part II: Becoming a Functional C++ Programmer

The string type is not intrinsic to C++ like int or float, meaning that its operations are not built into the syntax of the language. Operations on string type variables are defined in the string include file. The string class is discussed further in Chapter 27. I mention string here to demon­ strate that it is often easier to use than manipulating null terminated charac­ ter arrays yourself.