Xem mẫu

out << startLevel << htmlLine << endLevel << endl; } break; // Out of while loop } } } ///:~ Item contains a private member function removeBar( ) that is used internally to strip off the leading bars, if they appear. The constructor for Item initializes depth to 0 to indicate that no ‘#’ signs were found yet; if none are found then it is assumed the Item should be displayed at level one. Each character in the string is examined using operator[ ] to find the depth, id and url values. The other member functions simply return these values. After opening the files, main( ) uses string::find( ) to locate the line containing the site map data. At this point, substr( ) is used in order to strip off the information before and after the site map data. The subsequent while loop performs the parsing, but notice that the value index is passed by reference into the Item constructor, and that constructor increments index as it parses each new Item, thus moving forward in the sequence. If an Item is at level one, then an HTML h1 tag is used, otherwise the elements are indented using HTML non-breaking spaces. Note in the initialization of htmlLine how easy it is to construct a string – you can just combine quoted character arrays and other string objects using operator+. When the output is written to the destination file, startLevel and endLevel will only produce results if they have been given any value other than their default initialization values. Summary C++ string objects provide developers with a number of great advantages over their C counterparts. For the most part, the string class makes referring to strings through the use of character pointers unnecessary. This eliminates an entire class of software defects that arise from the use of uninitialized and incorrectly valued pointers. C++ strings dynamically and transparently grow their internal data storage space to accommodate increases in the size of the string data. This means that when the data in a string grows beyond the limits of the memory initially allocated to it, the string object will make the memory management calls that take space from and return space to the heap. Consistent allocation schemes prevent memory leaks and have the potential to be much more efficient than “roll your own” memory management. The string class member functions provide a fairly comprehensive set of tools for creating, modifying, and searching in strings. string comparisons are always case sensitive, but you can work around this by copying string data to C style null terminated strings and using case Chapter 14: Templates & Container Classes 61 insensitive string comparison functions, temporarily converting the data held in sting objects to a single case, or by creating a case insensitive string class which overrides the character traits used to create the basic_string object. Exercises 1. A palindrome is a word or group of words that read the same forward and backward. For example “madam” or “wow”. Write a program that takes a string argument from the command line and returns TRUE if the string was a palindrome. 2. Sometimes the input from a file stream contains a two character sequence to represent a newline. These two characters (0x0a 0x0d) produce extra blank lines when the stream is printed to standard out. Write a program that finds the character 0x0d (ASCII carriage return) and deletes it from the string. 3. Write a program that reverses the order of the characters in a string. Chapter 14: Templates & Container Classes 62 2: Iostreams There’s much more you can do with the general I/O problem than just take standard I/O and turn it into a class. Wouldn’t it be nice if you could make all the usual “receptacles” – standard I/O, files and even blocks of memory – look the same, so you need to remember only one interface? That’s the idea behind iostreams. They’re much easier, safer, and often more efficient than the assorted functions from the Standard C stdio library. Iostream is usually the first class library that new C++ programmers learn to use. This chapter explores the use of iostreams, so they can replace the C I/O functions through the rest of the book. In future chapters, you’ll see how to set up your own classes so they’re compatible with iostreams. Why iostreams? You may wonder what’s wrong with the good old C library. And why not “wrap” the C library in a class and be done with it? Indeed, there are situations when this is the perfect thing to do, when you want to make a C library a bit safer and easier to use. For example, suppose you want to make sure a stdio file is always safely opened and properly closed, without relying on the user to remember to call the close( ) function: //: C02:FileClass.h // Stdio files wrapped #ifndef FILECLAS_H #define FILECLAS_H #include class FileClass { std::FILE* f; public: FileClass(const char* fname, const char* mode="r"); ~FileClass(); std::FILE* fp(); }; #endif // FILECLAS_H ///:~ 63 In C when you perform file I/O, you work with a naked pointer to a FILE struct, but this class wraps around the pointer and guarantees it is properly initialized and cleaned up using the constructor and destructor. The second constructor argument is the file mode, which defaults to “r” for “read.” To fetch the value of the pointer to use in the file I/O functions, you use the fp( ) access function. Here are the member function definitions: //: C02:FileClass.cpp {O} // Implementation #include "FileClass.h" #include using namespace std; FileClass::FileClass(const char* fname, const char* mode){ f = fopen(fname, mode); if(f == NULL) { printf("%s: file not found\n", fname); exit(1); } } FileClass::~FileClass() { fclose(f); } FILE* FileClass::fp() { return f; } ///:~ The constructor calls fopen( ),as you would normally do, but it also checks to ensure the result isn’t zero, which indicates a failure upon opening the file. If there’s a failure, the name of the file is printed and exit( ) is called. The destructor closes the file, and the access function fp( )returns f. Here’s a simple example using class FileClass: //: C02:FileClassTest.cpp //{L} FileClass // Testing class File #include "FileClass.h" #include "../require.h" using namespace std; int main(int argc, char* argv[]) { requireArgs(argc, 1); FileClass f(argv[1]); // Opens and tests const int bsize = 100; char buf[bsize]; while(fgets(buf, bsize, f.fp())) Chapter 14: Templates & Container Classes 64 puts(buf); } // File automatically closed by destructor ///:~ You create the FileClass object and use it in normal C file I/O function calls by calling fp( ). When you’re done with it, just forget about it, and the file is closed by the destructor at the end of the scope. True wrapping Even though the FILE pointer is private, it isn’t particularly safe because fp( ) retrieves it. The only effect seems to be guaranteed initialization and cleanup, so why not make it public, or use a struct instead? Notice that while you can get a copy of f using fp( ), you cannot assign to f – that’s completely under the control of the class. Of course, after capturing the pointer returned by fp( ), the client programmer can still assign to the structure elements, so the safety is in guaranteeing a valid FILE pointer rather than proper contents of the structure. If you want complete safety, you have to prevent the user from direct access to the FILE pointer. This means some version of all the normal file I/O functions will have to show up as class members, so everything you can do with the C approach is available in the C++ class: //: C02:Fullwrap.h // Completely hidden file IO #ifndef FULLWRAP_H #define FULLWRAP_H class File { std::FILE* f; std::FILE* F(); // Produces checked pointer to f public: File(); // Create object but don`t open file File(const char* path, const char* mode = "r"); ~File(); int open(const char* path, const char* mode = "r"); int reopen(const char* path, const char* mode); int getc(); int ungetc(int c); int putc(int c); int puts(const char* s); char* gets(char* s, int n); int printf(const char* format, ...); size_t read(void* ptr, size_t size, Chapter 14: Templates & Container Classes 65 ... - tailieumienphi.vn
nguon tai.lieu . vn