To get a copy of a string, you need to do more. First, you need to allocate memory to hold the string. You can do this by declaring a second array or by using new. The second approach enables you to custom fit the storage to the string:
ps = new char[strlen(animal) + 1]; // get new storage
The string "fox" doesn’t completely fill the animal array, so this approach wastes space. This bit of code uses strlen() to find the length of the string; it adds one to get the length, including the null character. Then the program uses new to allocate just enough space to hold the string.
Next, you need a way to copy a string from the animal array to the newly allocated space. It doesn’t work to assign animal to ps because that just changes the address stored in ps and thus loses the only way the program had to access the newly allocated memory. Instead, you need to use the strcpy() library function:
strcpy(ps, animal); // copy string to new storage
The strcpy() function takes two arguments. The first is the destination address, and the second is the address of the string to be copied. It’s up to you to make certain that the destination really is allocated and has sufficient space to hold the copy. That’s accomplished here by using strlen() to find the correct size and using new to get free memory.
Note that by using strcpy() and new, you get two separate copies of "fox":
fox at 0x0065fd30
fox at 0x004301c8
Also note that new located the new storage at a memory location quite distant from that of the array animal.
Often you encounter the need to place a string into an array. You use the = operator when you initialize an array; otherwise, you use strcpy() or strncpy(). You’ve seen the strcpy() function; it works like this:
char food[20] = "carrots"; // initialization
strcpy(food, "flan"); // otherwise
Note that something like the following can cause problems because the food array is smaller than the string:
strcpy(food, "a picnic basket filled with many goodies");
In this case, the function copies the rest of the string into the memory bytes immediately following the array, which can overwrite other memory the program is using. To avoid that problem, you should use strncpy() instead. It takes a third argument: the maximum number of characters to be copied. Be aware, however, that if this function runs out of space before it reaches the end of the string, it doesn’t add the null character. Thus, you should use the function like this:
strncpy(food, "a picnic basket filled with many goodies", 19);
food[19] = '\0';
This copies up to 19 characters into the array and then sets the last element to the null character. If the string is shorter than 19 characters, strncpy() adds a null character earlier to mark the true end of the string.
Caution
Use strcpy() or strncpy(), not the assignment operator, to assign a string to an array.
Now that you’ve seen some aspects of using C-style strings and the cstring library, you can appreciate the comparative simplicity of using the C++ string type. You (normally) don’t have to worry about a string overflowing an array, and you can use the assignment operator instead of strcpy() or strncpy().
Using new to Create Dynamic Structures
You’ve seen how it can be advantageous to create arrays during runtime rather than at compile time. The same holds true for structures. You need to allocate space for only as many structures as a program needs during a particular run. Again, the new operator is the tool to use. With it, you can create dynamic structures. Again,
Using new with structures has two parts: creating the structure and accessing its members. To create a structure, you use the structure type with new. For example, to create an unnamed structure of the inflatable type and assign its address to a suitable pointer, you can use the following:
inflatable * ps = new inflatable;
This assigns to ps the address of a chunk of free memory large enough to hold a structure of the inflatable type. Note that the syntax is exactly the same as it is for C++’s built-in types.
The tricky part is accessing members. When you create a dynamic structure, you can’t use the dot membership operator with the structure name because the structure has no name. All you have is its address. C++ provides an operator just for this situation: the arrow membership operator (->). This operator, formed by typing a hyphen and then a greater-than symbol, does for pointers to structures what the dot operator does for structure names. For example, if ps points to a type inflatable structure, then ps->price is the price member of the pointed-to structure (see Figure 4.11).
Figure 4.11. Identifying structure members.
Tip