Informally, you can say that you’re passing a string as an argument, but you’re really passing the address of the first character in the string. This implies that a string function prototype should use type char * as the type for the formal parameter representing a string.
One important difference between a C-style string and a regular array is that the string has a built-in terminating character. (Recall that a char array containing characters but no null character is just an array and not a string.) That means you don’t have to pass the size of the string as an argument. Instead, the function can use a loop to examine each character in the string in turn until the loop reaches the terminating null character. Listing 7.9 illustrates that approach with a function that counts the number of times a given character appears in a string. Because the program doesn’t need to deal with negative values, it uses unsigned int as the type for counting.
Listing 7.9. strgfun.cpp
// strgfun.cpp -- functions with a string argument
#include
unsigned int c_in_str(const char * str, char ch);
int main()
{
using namespace std;
char mmm[15] = "minimum"; // string in an array
// some systems require preceding char with static to
// enable array initialization
char *wail = "ululate"; // wail points to string
unsigned int ms = c_in_str(mmm, 'm');
unsigned int us = c_in_str(wail, 'u');
cout << ms << " m characters in " << mmm << endl;
cout << us << " u characters in " << wail << endl;
return 0;
}
// this function counts the number of ch characters
// in the string str
unsigned int c_in_str(const char * str, char ch)
{
unsigned int count = 0;
while (*str) // quit when *str is '\0'
{
if (*str == ch)
count++;
str++; // move pointer to next char
}
return count;
}
Here’s the output of the program in Listing 7.9:
3 m characters in minimum
2 u characters in ululate
Program Notes
Because the c_int_str() function in Listing 7.9 shouldn’t alter the original string, it uses the const modifier when it declares the formal parameter str. Then if you mistakenly let the function alter part of the string, the compiler catches your error. Of course, you can use array notation instead to declare str in the function header:
unsigned int c_in_str(const char str[], char ch) // also okay
However, using pointer notation reminds you that the argument doesn’t have to be the name of an array but can be some other form of pointer.
The function itself demonstrates a standard way to process the characters in a string:
while (*str)
{
statements
str++;
}
Initially, str points to the first character in the string, so *str represents the first character itself. For example, immediately after the first function call, *str has the value m, the first character in minimum. As long as the character is not the null character (\0), *str is nonzero, so the loop continues. At the end of each loop, the expression str++ increments the pointer by 1 byte so that it points to the next character in the string. Eventually, str points to the terminating null character, making *str equal to 0, which is the numeric code for the null character. That condition terminates the loop. (Why are string-processing functions ruthless? Because they stop at nothing.)
Functions That Return C-Style Strings
Now suppose you want to write a function that returns a string. Well, a function can’t do that. But it can return the address of a string, and that’s more efficient. Listing 7.10, for example, defines a function called buildstr() that returns a pointer. This function takes two arguments: a character and a number. Using new, the function creates a string whose length equals the number, and then it initializes each element to the character. Then it returns a pointer to the new string.
Listing 7.10. strgback.cpp
// strgback.cpp -- a function that returns a pointer to char
#include
char * buildstr(char c, int n); // prototype
int main()
{
using namespace std;
int times;
char ch;
cout << "Enter a character: ";
cin >> ch;
cout << "Enter an integer: ";
cin >> times;
char *ps = buildstr(ch, times);
cout << ps << endl;
delete [] ps; // free memory
ps = buildstr('+', 20); // reuse pointer
cout << ps << "-DONE-" << ps << endl;
delete [] ps; // free memory
return 0;
}
// builds string made of n c characters
char * buildstr(char c, int n)
{
char * pstr = new char[n + 1];
pstr[n] = '\0'; // terminate string
while (n-- > 0)
pstr[n] = c; // fill rest of string
return pstr;
}
Here’s a sample run of the program in Listing 7.10:
Enter a character: V
Enter an integer: 46
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
++++++++++++++++++++-DONE-++++++++++++++++++++
Program Notes