<< " static: " << (void *) buffer < cout << "Memory contents:\n"; for (i = 0; i < N; i++) { cout << pd1[i] << " at " << &pd1[i] << "; "; cout << pd2[i] << " at " << &pd2[i] << endl; } cout << "\nCalling new and placement new a second time:\n"; double *pd3, *pd4; pd3= new double[N]; // find new address pd4 = new (buffer) double[N]; // overwrite old data for (i = 0; i < N; i++) pd4[i] = pd3[i] = 1000 + 40.0 * i; cout << "Memory contents:\n"; for (i = 0; i < N; i++) { cout << pd3[i] << " at " << &pd3[i] << "; "; cout << pd4[i] << " at " << &pd4[i] << endl; } cout << "\nCalling new and placement new a third time:\n"; delete [] pd1; pd1= new double[N]; pd2 = new (buffer + N * sizeof(double)) double[N]; for (i = 0; i < N; i++) pd2[i] = pd1[i] = 1000 + 60.0 * i; cout << "Memory contents:\n"; for (i = 0; i < N; i++) { cout << pd1[i] << " at " << &pd1[i] << "; "; cout << pd2[i] << " at " << &pd2[i] << endl; } delete [] pd1; delete [] pd3; return 0; } Here is the output from the program in Listing 9.10 on one system: Calling new and placement new: Memory addresses: heap: 006E4AB0 static: 00FD9138 Memory contents: 1000 at 006E4AB0; 1000 at 00FD9138 1020 at 006E4AB8; 1020 at 00FD9140 1040 at 006E4AC0; 1040 at 00FD9148 1060 at 006E4AC8; 1060 at 00FD9150 1080 at 006E4AD0; 1080 at 00FD9158 Calling new and placement new a second time: Memory contents: 1000 at 006E4B68; 1000 at 00FD9138 1040 at 006E4B70; 1040 at 00FD9140 1080 at 006E4B78; 1080 at 00FD9148 1120 at 006E4B80; 1120 at 00FD9150 1160 at 006E4B88; 1160 at 00FD9158 Calling new and placement new a third time: Memory contents: 1000 at 006E4AB0; 1000 at 00FD9160 1060 at 006E4AB8; 1060 at 00FD9168 1120 at 006E4AC0; 1120 at 00FD9170 1180 at 006E4AC8; 1180 at 00FD9178 1240 at 006E4AD0; 1240 at 00FD9180 Program Notes The first thing to note about Listing 9.10 is that placement new does, indeed, place the p2 array in the buffer array; both p2 and buffer have the value 00FD9138. They are, however, of different types; p1 is pointer-to-double, whereas buffer is pointer-to-char. (By the way, that’s why the program uses a (void *) cast for buffer; otherwise, cout would try to display a string.) Meanwhile, regular new locates the p1 array rather far away in memory, at location 006E4AB0, which is part of the dynamically managed heap. The second point to note is that the second call to regular new results in new finding a new block of memory—one beginning at 006E4B68. But the second call to placement new results in the same block of memory being used as before—that is, the block beginning at 00FD9138. The important fact here is that placement new simply uses the address that is passed to it; it doesn’t keep track of whether that location has already been used, and it doesn’t search the block for unused memory. This shifts some of the burden of memory management to the programmer. For example, the third call to placement new provides an offset into the buffer array so that new memory is used: pd2 = new (buffer + N * sizeof(double)) double[N]; // offset of 40 bytes The third point has to do with the use and nonuse of delete. For regular new, the following statement frees up the block of memory beginning at 006E4AB0, and as a result, the next call to new is able to reuse that block: delete [] pd1; In contrast, the program in Listing 9.10 does not use delete to free the memory used by placement new. In fact, in this case, it can’t. The memory specified by buffer is static memory, and delete can be used only with a pointer to heap memory allocated by regular new. That is, the buffer array is outside the jurisdiction of delete, and the following statement will produce a runtime error: delete [] pd2; // won't work On the other hand, if you use regular new to create a buffer in the first place, you use regular delete to free that entire block. Another way you can use placement new is to combine it with new initialization to place information at a specific hardware address. You may wonder exactly what the placement new function does. Basically, it does nothing other than return the address passed to it, type casting it to void * so that it can be assigned to any pointer type. But that’s the default placement new. C++ allows programmers to overload placement new. The situation becomes more involved when you use placement new with class objects. Chapter 12, “Classes and Dynamic Memory Allocation,” continues this story. Other Forms of Placement new Just as regular new invokes a new function with one argument, the standard placement new invokes a new function with two arguments: int * pi = new int; // invokes new(sizeof(int)) int * p2 = new(buffer) int; // invokes new(sizeof(int), buffer) int * p3 = new(buffer) int[40]; // invokes new(40*sizeof(int), buffer) The placement new function is not replaceable, but it can be overloaded. It needs at least two parameters, the first of which always is a std::size_t parameter designating the number of bytes requested. Any such overloaded function is termed a placement new, even if the additional parameters don’t specify a location. Namespaces Names in C++ can refer to variables, functions, structures, enumerations, classes, and class and structure members. When programming projects grow large, the potential for name conflicts increases. When you use class libraries from more than one source, you can get name conflicts. For example, two libraries might both define classes named List, Tree, and Node, but in incompatible ways. You might want the List class from one library and the Tree from the other, and each might expect its own version of Node. Such conflicts are termed The C++ Standard provides namespace facilities to provide greater control over the scope of names. It took a while for compilers to incorporate namespaces, but, by now, support has become common. Traditional C++ Namespaces Before looking at the new namespace facilities in C++, let’s review the namespace properties that already exist in C++ and introduce some terminology. This can help make the idea of namespaces seem more familiar. One term you need to be aware of is A second term you need to be aware of is However, a variable might not be visible everywhere in its potential scope. For instance, it might be hidden by another variable of the same name declared in a nested declarative region. For example, a local variable declared in a function (for this variable, the declarative region is the function) hides a global variable declared in the same file (for this variable, the declarative region is the file). The portion of the program that can actually see the variable is termed the Figure 9.5. Declarative regions. Figure 9.6. Potential scope and scope. C++’s rules about global and local variables define a kind of namespace hierarchy. Each declarative region can declare names that are independent of names declared in other declarative regions. A local variable declared in one function doesn’t conflict with a local variable declared in a second function. New Namespace Features C++ now adds the ability to create named namespaces by defining a new kind of declarative region, one whose main purpose is to provide an area in which to declare names. The names in one namespace don’t conflict with the same names declared in other namespaces, and there are mechanisms for letting other parts of a program use items declared in a namespace. The following code, for example, uses the new keyword namespace to create two namespaces, Jack and Jill: namespace Jack { double pail; // variable declaration void fetch(); // function prototype int pal; // variable declaration struct Well { ... }; // structure declaration } namespace Jill { double bucket(double n) { ... } // function definition double fetch; // variable declaration int pal; // variable declaration struct Hill { ... }; // structure declaration } Namespaces can be located at the global level or inside other namespaces, but they cannot be placed in a block. Thus, a name declared in a namespace has external linkage by default (unless it refers to a constant). In addition to user-defined namespaces, there is one more namespace, the The names in any one namespace don’t conflict with names in another namespace. Thus, the fetch in Jack can coexist with the fetch in Jill, and the Hill in Jill can coexist with an external Hill. The rules governing declarations and definitions in a namespace are the same as the rules for global declarations and definitions. Namespaces are namespace Jill { char * goose(const char *); } Similarly, the original Jack namespace provides a prototype for a fetch() function. You can provide the code for the function later in the file (or in another file) by using the Jack namespace again: namespace Jack { void fetch() { ... } } Of course, you need a way to access names in a given namespace. The simplest way is to use ::, the scope-resolution operator, to Jack::pail = 12.34; // use a variable Jill::Hill mole; // create a type Hill structure Jack::fetch(); // use a function An unadorned name, such as pail, is termed the using Declarations and using Directives Having to qualify names every time they are used is not always an appealing prospect, so C++ provides two mechanisms—the using The using declaration involves preceding a qualified name with the keyword using: using Jill::fetch; // a using declaration A using declaration adds a particular name to the declarative region in which it occurs. For example, the using declaration of Jill::fetch in main() adds fetch to the declarative region defined by main(). After making this declaration, you can use the name fetch instead of Jill::fetch. The following code fragment illustrates these points: namespace Jill { double bucket(double n) { ... } double fetch; struct Hill { ... }; } char fetch; int main() { using Jill::fetch; // put fetch into local namespace double fetch; // Error! Already have a local fetch cin >> fetch; // read a value into Jill::fetch cin >> ::fetch; // read a value into global fetch ... } Because a using declaration adds the name to the local declarative region, this example precludes creating another local variable by the name of fetch. Also like any other local variable, fetch would override a global variable by the same name. Placing a using declaration at the external level adds the name to the global namespace: void other(); namespace Jill { double bucket(double n) { ... } double fetch; struct Hill { ... }; } using Jill::fetch; // put fetch into global namespace int main() { cin >> fetch; // read a value into Jill::fetch other() ... } void other() { cout << fetch; // display Jill::fetch ... } A using declaration, then, makes a single name available. In contrast, the using directive makes using namespace Jack; // make all the names in Jack available Placing a using directive at the global level makes the namespace names available globally. You’ve seen this in action a few times in this book in the following form: #include using namespace std; // make names available globally Placing a using directive in a particular function makes the names available just in that function. Here’s an example: int main() { using namespace jack; // make names available in vorn() ... } You’ve seen this form often in this book with the std namespace. One thing to keep in mind about using directives and using declarations is that they increase the possibility of name conflicts. That is, if you have both namespace jack and namespace jill available, and you use the scope-resolution operator, there is no ambiguity: jack::pal = 3; jill::pal =10; The variables jack::pal and jill::pal are distinct identifiers for distinct memory locations. However, if you employ using declarations, the situation changes: using jack::pal; using jill::pal; pal = 4; // which one? now have a conflict In fact, the compiler won’t let you use both of these using declarations because of the ambiguity that would be created. using Directives Versus using Declarations Using a using directive to import all the names from a namespace wholesale is namespace Jill { double bucket(double n) { ... } double fetch; struct Hill { ... }; } char fetch; // global namespace int main() { using namespace Jill; // import all namespace names Hill Thrill; // create a type Jill::Hill structure double water = bucket(2); // use Jill::bucket(); double fetch; // not an error; hides Jill::fetch cin >> fetch; // read a value into the local fetch cin >> ::fetch; // read a value into global fetch cin >> Jill::fetch; // read a value into Jill::fetch ... } int foom() { Hill top; // ERROR Jill::Hill crest; // valid } Here, in main(), the name Jill::fetch is placed in the local namespace. It doesn’t have local scope, so it doesn’t override the global fetch. But the locally declared fetch hides both Jill::fetch and the global fetch. However, both of the last two fetch variables are available if you use the scope-resolution operator. You might want to compare this example to the preceding one, which uses a using declaration. One other point of note is that although a using directive in a function treats the namespace names as being declared outside the function, it doesn’t make those names available to other functions in the file. Hence in the preceding example, the foom() function can’t use the unqualified Hill identifier. Note Suppose a namespace and a declarative region both define the same name. If you attempt to use a using declaration to bring the namespace name into the declarative region, the two names conflict, and you get an error. If you use a using directive to bring the namespace name into the declarative region, the local version of the name hides the namespace version. Generally speaking, the using declaration is safer to use than a using directive because it shows exactly what names you are making available. And if the name conflicts with a local name, the compiler lets you know. The using directive adds all names, even ones you might not need. If a local name conflicts, it overrides the namespace version, and you aren’t warned. Also the open nature of namespaces means that the complete list of names in a namespace might be spread over several locations, making it difficult to know exactly which names you are adding. This is the approach used for most of this book’s examples: #include int main() { using namespace std; First, the iostream header file puts everything in the std namespace. Then, the using directive makes the names available within main(). Some examples do this instead: #include using namespace std; int main() { This exports everything from the std namespace into the global namespace. The main rationale for this approach is expediency. It’s easy to do, and if your system doesn’t have namespaces, you can replace the first two of the preceding code lines with the original form: #include However, namespace proponents hope that you will be more selective and use either the scope-resolution operator or the using declaration. That is, you shouldn’t use the following: using namespace std; // avoid as too indiscriminate Instead, you should use this: int x; std::cin >> x; std::cout << x << std::endl; Or you could use this: using std::cin; using std::cout; using std::endl; int x; cin >> x; cout << x << endl; You can use nested namespaces, as described in the following section, to create a namespace that holds the using declarations you commonly use. More Namespace Features You can nest namespace declarations, like this: namespace elements { namespace fire { int flame; ... } float water; } In this case, you refer to the flame variable as elements::fire::flame. Similarly, you can make the inner names available with this using directive: using namespace elements::fire; Also you can use using directives and using declarations inside namespaces, like this: namespace myth { using Jill::fetch; using namespace elements; using std::cout; using std::cin; } Suppose you want to access Jill::fetch. Because Jill::fetch is now part of the myth namespace, where it can be called fetch, you can access it this way: std::cin >> myth::fetch; Of course, because it is also part of the Jill namespace, you still can call it Jill::fetch: std::cout << Jill::fetch; // display value read into myth::fetch Or you can do this, provided that no local variables conflict: using namespace myth; cin >> fetch; // really std::cin and Jill::fetch Now consider applying a using directive to the using namespace myth; This single directive has the same effect as the following two directives: using namespace myth; using namespace elements; You can create an alias for a namespace. For example, suppose you have a namespace defined as follows: namespace my_very_favorite_things { ... }; You can make mvft an alias for my_very_favorite_things by using the following statement: namespace mvft = my_very_favorite_things; You can use this technique to simplify using nested namespaces: namespace MEF = myth::elements::fire; using MEF::flame; Unnamed Namespaces You can create an namespace // unnamed namespace { int ice; int bandycoot; } This code behaves as if it were followed by a using directive; that is, the names declared in this namespace are in potential scope until the end of the declarative region that contains the unnamed namespace. In this respect, names in an unnamed namespace are like global variables. However, if a namespace has no name, you can’t explicitly use a using directive or using declaration to make the names available elsewhere. In particular, you can’t use names from an unnamed namespace in a file other than the one that contains the namespace declaration. This provides an alternative to using static variables with internal linkage. Suppose, for example, you have this code: static int counts; // static storage, internal linkage int other(); int main() { ... } int other() { ... } The namespace approach is to do this instead: namespace { int counts; // static storage, internal linkage } int other(); int main() { ... } int other() { ... } A Namespace Example Let’s take a look at a multifile example that demonstrates some of the features of namespaces. The first file in this example (see Listing 9.11) is a header file that contains some items normally found in header files—constants, structure definitions, and function prototypes. In this case, the items are placed in two namespaces. The first namespace, pers, contains a definition of a Person structure, plus prototypes for a function that fills a structure with a person’s name and a function that displays the structure’s contents. The second namespace, debts, defines a structure for storing the name of a person and the amount of money owed to that person. This structure uses the Person structure, so the debts namespace has a using directive to make the names in the pers namespace available in the debts namespace. The debts namespace also contains some prototypes. Listing 9.11. namesp.h. // namesp.h #include // create the pers and debts namespaces namespace pers { struct Person { std::string fname; std::string lname; }; void getPerson(Person &); void showPerson(const Person &); } namespace debts { using namespace pers; struct Debt { Person name; double amount; }; void getDebt(Debt &); void showDebt(const Debt &); double sumDebts(const Debt ar[], int n); } The second file in this example (see Listing 9.12) follows the usual pattern of having a source code file provide definitions for functions prototyped in a header file. The function names, which are declared in a namespace, have namespace scope, so the definitions need to be in the same namespace as the declarations. This is where the open nature of namespaces comes in handy. The original namespaces are brought in by including namesp.h (refer to Listing 9.11). The file then adds the function definitions to the two namespaces, as shown in Listing 9.12. Also the namesp.cpp file illustrates bringing in elements of the std namespace with the using declaration and the scope-resolution operator. Listing 9.12. namesp.cpp // namesp.cpp -- namespaces #include #include "namesp.h" namespace pers { using std::cout; using std::cin; void getPerson(Person & rp) { cout << "Enter first name: "; cin >> rp.fname; cout << "Enter last name: "; cin >> rp.lname; } void showPerson(const Person & rp) { std::cout << rp.lname << ", " << rp.fname; } } namespace debts { void getDebt(Debt & rd) { getPerson(rd.name); std::cout << "Enter debt: "; std::cin >> rd.amount; } void showDebt(const Debt & rd) { showPerson(rd.name); std::cout <<": $" << rd.amount << std::endl; } double sumDebts(const Debt ar[], int n) { double total = 0; for (int i = 0; i < n; i++) total += ar[i].amount; return total; } } Finally, the third file of this program (see Listing 9.13) is a source code file that uses the structures and functions declared and defined in the namespaces. Listing 9.13 shows several methods of making the namespace identifiers available. Listing 9.13. usenmsp.cpp // usenmsp.cpp -- using namespaces #include #include "namesp.h" void other(void); void another(void); int main(void) { using debts::Debt; using debts::showDebt; Debt golf = { {"Benny", "Goatsniff"}, 120.0 }; showDebt(golf); other(); another(); return 0; } void other(void) { using std::cout; using std::endl; using namespace debts; Person dg = {"Doodles", "Glister"}; showPerson(dg); cout << endl; Debt zippy[3]; int i; for (i = 0; i < 3; i++) getDebt(zippy[i]); for (i = 0; i < 3; i++) showDebt(zippy[i]); cout << "Total debt: $" << sumDebts(zippy, 3) << endl; return; } void another(void) { using pers::Person; Person collector = { "Milo", "Rightshift" }; pers::showPerson(collector); std::cout << std::endl; } In Listing 9.13, main() begins by using two using declarations: using debts::Debt; // makes the Debt structure definition available using debts::showDebt; // makes the showDebt function available Note that using declarations just use the name; for example, the second example here doesn’t describe the return type or function signature for showDebt; it just gives the name. (Thus, if a function were overloaded, a single using declaration would import all the versions.) Also although both Debt and showDebt() use the Person type, it isn’t necessary to import any of the Person names because the debt namespace already has a using directive that includes the pers namespace. Next, the other() function takes the less desirable approach of importing the entire namespace with a using directive: using namespace debts; // make all debts and pers names available to other() Because the using directive in debts imports the pers namespace, the other() function can use the Person type and the showPerson() function. Finally, the another() function uses a using declaration and the scope-resolution operator to access specific names: using pers::Person;; pers::showPerson(collector); Here is a sample run of the program built from Listings 9.11, 9.12, and 9.13: Goatsniff, Benny: $120 Glister, Doodles Enter first name: Arabella Enter last name: Binx Enter debt: 100 Enter first name: Cleve Enter last name: Delaproux Enter debt: 120 Enter first name: Eddie Enter last name: Fiotox Enter debt: 200 Binx, Arabella: $100 Delaproux, Cleve: $120 Fiotox, Eddie: $200 Total debt: $420 Rightshift, Milo Namespaces and the Future As programmers become more familiar with namespaces, common programming idioms will emerge. Here are some current guidelines: • Use variables in a named namespace instead of using external global variables. • Use variables in an unnamed namespace instead of using static global variables. • If you develop a library of functions or classes, place them in a namespace. Indeed, C++ currently already calls for placing standard library functions in a namespace called std. This extends to functions brought in from C. For example, the math.c header file, which is C-compatible, doesn’t use namespaces, but the C++ cmath header file should place the various math library functions in the std namespace. • Use the using directive only as a temporary means of converting old code to namespace usage. • Don’t use using directives in header files; for one thing, doing so conceals which names are being made available. Also the ordering of header files may affect behavior. If you use a using directive, place it after all the preprocessor #include directives. • Preferentially import names by using the scope-resolution operator or a using declaration. • Preferentially use local scope instead of global scope for using declarations. Bear in mind that the main motivation for using namespaces is to simplify management of large programming projects. For simple, one-file programs, using a using directive is no great sin. As mentioned earlier, changes in the header filenames reflect namespace changes. The older-style header files, such as iostream.h, do not use namespaces, but the newer iostream header file should use the std namespace. Summary C++ encourages the use of multiple files in developing programs. An effective organizational strategy is to use a header file to define user types and provide function prototypes for functions to manipulate the user types. You should use a separate source code file for the function definitions. Together, the header file and the source file define and implement the user-defined type and how it can be used. Then, main() and other functions using those functions can go into a third file. C++’s storage schemes determine how long variables remain in memory (storage duration) and what parts of a program have access to them (scope and linkage). Automatic variables are variables that are defined within a block, such as a function body or a block within the body. They exist and are known only while the program executes statements in the block that contains the definition. Automatic variables may be declared by using the storage class specifier register or with no specifier at all, in which case the variable is automatically automatic. The register specifier was a hint to the compiler that the variable is heavily used, but that use is deprecated under C++11. Static variables exist for the duration of a program. A variable defined outside any function is known to all functions in the file following its definition (file scope) and is made available to other files in the program (external linkage). For another file to use such a variable, that file must declare it by using the extern keyword. A variable that is shared across files should have a defining declaration in one file (extern needn’t be used but it can be used if combined with initialization) and reference declarations in the other files (extern is used with no initialization.). A variable defined outside any function but qualified with the keyword static has file scope but is not made available to other files (internal linkage). A variable defined inside a block but qualified with the keyword static is local to that block (local scope, no linkage) but retains its value for the duration of the program. By default, C++ functions have external linkage, so they can be shared across files. But functions qualified with the keyword static have internal linkage and are confined to the defining file. Dynamic memory allocation and deallocation, using new and delete, uses the free store, or heap, for data. The memory comes into use when new is called and is freed when delete is called. The program uses pointers to keep track of these memory locations. Namespaces let you define named regions in which you can declare identifiers. The intent is to reduce name conflicts, particularly in large programs that use code from several vendors. You can make available identifiers in a namespace by using the scope-resolution operator, by using a using declaration, or by using a using directive. Chapter Review 1. What storage scheme would you use for the following situations? a. homer is a formal argument (parameter) to a function. b. The secret variable is to be shared by two files. c. The topsecret variable is to be shared by the functions in one file but hidden from other files. d. beencalled keeps track of how many times the function containing it has been called. 2. Describe the differences between a using declaration and a using directive. 3. Rewrite the following so that it doesn’t use using declarations or using directives: #include using namespace std; int main() { double x; cout << "Enter value: "; while (! (cin >> x) ) { cout << "Bad input. Please enter a number: "; cin.clear(); while (cin.get() != '\n') continue; } cout << "Value = " << x << endl; return 0; } 4. Rewrite the following so that it uses using declarations instead of the using directive: #include using namespace std; int main() { double x; cout << "Enter value: "; while (! (cin >> x) ) { cout << "Bad input. Please enter a number: "; cin.clear(); while (cin.get() != '\n') continue; } cout << "Value = " << x << endl; return 0; } 5. Suppose you want the average(3,6) function to return an int average of the two int arguments when it is called in one file, and you want it to return a double average of the two int arguments when it is called in a second file in the same program. How could you set this up? 6. What will the following two-file program display? // file1.cpp #include using namespace std; void other(); void another(); int x = 10; int y; int main() { cout << x << endl; { int x = 4; cout << x << endl; cout << y << endl; } other(); another(); return 0; } void other() { int y = 1; cout << "Other: " << x << ", " << y << endl; } // file 2.cpp #include using namespace std; extern int x; namespace { int y = -4; } void another() { cout << "another(): " << x << ", " << y << endl; } 7. What will the following program display? #include using namespace std; void other(); namespace n1 { int x = 1; } namespace n2 { int x = 2; } int main() { using namespace n1; cout << x << endl; { int x = 4; cout << x << ", " << n1::x << ", " << n2::x << endl; } using n2::x; cout << x << endl; other(); return 0; } void other() { using namespace n2; cout << x << endl; { int x = 4; cout << x << ", " << n1::x << ", " << n2::x << endl; } using n2::x; cout << x << endl; } Programming Exercises 1. Here is a header file: // golf.h -- for pe9-1.cpp const int Len = 40; struct golf { char fullname[Len]; int handicap; }; // non-interactive version: // function sets golf structure to provided name, handicap // using values passed as arguments to the function void setgolf(golf & g, const char * name, int hc); // interactive version: // function solicits name and handicap from user // and sets the members of g to the values entered // returns 1 if name is entered, 0 if name is empty string int setgolf(golf & g); // function resets handicap to new value void handicap(golf & g, int hc); // function displays contents of golf structure void showgolf(const golf & g); Note that setgolf() is overloaded. Using the first version of setgolf() would look like this: golf ann; setgolf(ann, "Ann Birdfree", 24); The function call provides the information that’s stored in the ann structure. Using the second version of setgolf() would look like this: golf andy; setgolf(andy); The function would prompt the user to enter the name and handicap and store them in the andy structure. This function could (but doesn’t need to) use the first version internally. Put together a multifile program based on this header. One file, named golf.cpp, should provide suitable function definitions to match the prototypes in the header file. A second file should contain main() and demonstrate all the features of the prototyped functions. For example, a loop should solicit input for an array of golf structures and terminate when the array is full or the user enters an empty string for the golfer’s name. The main() function should use only the prototyped functions to access the golf structures. 2. Redo Listing 9.9, replacing the character array with a string object. The program should no longer have to check whether the input string fits, and it can compare the input string to "" to check for an empty line. 3. Begin with the following structure declaration: struct chaff { char dross[20]; int slag; }; Write a program that uses placement new to place an array of two such structures in a buffer. Then assign values to the structure members (remembering to use strcpy() for the char array) and use a loop to display the contents. Option 1 is to use a static array, like that in Listing 9.10, for the buffer. Option 2 is to use regular new to allocate the buffer. 4. Write a three-file program based on the following namespace: namespace SALES { const int QUARTERS = 4; struct Sales { double sales[QUARTERS]; double average; double max; double min; }; // copies the lesser of 4 or n items from the array ar // to the sales member of s and computes and stores the // average, maximum, and minimum values of the entered items; // remaining elements of sales, if any, set to 0 void setSales(Sales & s, const double ar[], int n); // gathers sales for 4 quarters interactively, stores them // in the sales member of s and computes and stores the // average, maximum, and minimum values void setSales(Sales & s); // display all information in structure s void showSales(const Sales & s); } The first file should be a header file that contains the namespace. The second file should be a source code file that extends the namespace to provide definitions for the three prototyped functions. The third file should declare two Sales objects. It should use the interactive version of setSales() to provide values for one structure and the non-interactive version of setSales() to provide values for the second structure. It should display the contents of both structures by using showSales().