1. Trang chủ
  2. » Công Nghệ Thông Tin

HandBooks Professional Java-C-Scrip-SQL part 142 docx

6 97 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 29,58 KB

Nội dung

| | Quantum | Quantum | | Index Number | 5 | | + + | |Big | 0 | 2 + + + |Pointer | 1 | 10 | | | |Array | 2 | 12 | | | | | 3 | 14 | | | | | 4 | 11 | | | | +- + + | | + + | + + | | +- Quantum Item |± + | | Index Number Number | Quantum |Item | + + | 2 |Reference | 0 | 3 2 + + + |Array | 1 | 3 4 + + +-+ |(IRA) | 2 | 3 5 + + +-+-+ |segment | 3 | 3 3 + + + | | | |0 | 4 | 3 1 + + + | | | | | +- + + | | | | | | + + | | | | | + + | | | | | | +- | | | | | | | | Item # Offset Type Index | | | | | | | | + + | | | | | | | | 1 | 5 -+ VARSTRING 4 |±+-+ | | | | | | 2 | 17 +| VARSTRING 0 |±+ + + | | |Item | 3 | +-19 || VARSTRING 3 |±+ + | | |Index | 4 | ++-31 || VARSTRING 1 |±+ + | | | 5 |+++-38 || VARSTRING 2 |±+ + | | 6 |||| 38 || UNUSED 0 | | Quantum 3 | | ++++ ++ + + + | +- ||| |+ + | | ||| + + | | | ||+ + | | | | +- |+ + | | | | |Quantum | +-+ + +-+ + + | |Data | | BaldwinP.O.Box 0335NYSteve Heller11510| | | +- + + | | 333333333222222222211111111110000000000 | | 876543210987654321098765432109876543210 | + + We might use this facility to keep track of both customer records and inventory records, each of which would be logically separate although they may be stored in the same quantum file. In order to facilitate reconstruction of the file if part of the IRA is lost, we won't use the same quantum for items from two different arrays; as a result, the space freed by deleting an item will only be reused when an item is to be added to the same array. To find an element in a main object, we index into the main object index by the object's number, retrieving the quantum number of the big pointer array for that object. Then we calculate the IRA segment and the index into that segment and retrieve the quantum number and item number for the element we want. The last step is to use the item index to find the exact location of the element. Of course, we need a place to store the main object index. A normal application might have five or ten main objects; therefore, our allocation of 256 entries in the main object index is extremely generous in most cases. 11 The Light at the End of the Tunnel Let's start our examination of the implementation of the quantum file code by looking at a simple program that uses it to store a number of strings and then retrieve them (Figure flextest.00). Initial test program for quantum file implementation (quantum\flextest.cpp) (Figure flextest.00) codelist/flextest.00 Possibly the most striking feature of this program is how simple it appears, which is a direct consequence of the power of C++. Writing a similar program in C would require much greater knowledge of the implementation of the quantum file algorithm. However, in C++ all we have to know is which header file to include, how to open the quantum file, and how to create a FlexArray object, which behaves like a variable-sized array of variable-sized strings. Once we have dealt with this small set of prerequisites, we can use this extremely powerful and flexible data type in virtually the same way we would use a built-in type. Let's take a detailed look at exactly how we set up and use a quantum file in this program. First, we have a couple of statements that declare a temporary buffer variable which we'll use to construct data to store in the quantum file and delete any previous version of the quantum file itself. Next, we create a QuantumFile object called QF via the default constructor of the QuantumFile class. Then we call an Open function on that object, supplying the name of the quantum file to be created. The next statement creates a FlexArray object called TestArray. The arguments to this constructor are a pointer to the QuantumFile object that we'll use to store the data for TestArray, and a name by which we could reuse this same FlexArray object in another program or another execution of this program. Now we're up to the loop where we will start to use the TestArray object. The loop steps through the first 100 elements of TestArray, assigning each element a String consisting of digits corresponding to the position of that element in the TestArray object. The strstream named Temp is used to format the numeric values of the loop variable i into String values that can be stored in a FlexArray object. Finally, after we've put the values into TestArray, the second loop displays the values in the TestArray object. Pay No Attention to the Man Behind the Curtain At this point, I wouldn't be at all surprised if you had come to the conclusion that I have something up my sleeve and you would be right. Underneath this apparent simplicity is a wonderland of complex programming, which I hope I will be able to explain in an understandable way. Let's begin by examining some of these data types we've just seen, in enough detail to demystify them. The first of these data types is the String. As it happens, this is actually a typedef for a more general type called SVector, so we'll start with the question of exactly what an SVector might be. An SVector is very much like an array, with the following exceptions: 1. If you try to store something beyond the end of an SVector, you will get an error message rather than a mysterious crash. 2. You can find out how many elements an SVector has, by calling its size member function. 3. You can change the size of an SVector after it has been created, by calling its resize member function. 4. You can assign one SVector of a particular type to another SVector of the same type. 5. You can create an SVector by copying from another SVector of the same type. While these are very useful characteristics for any type of SVector, they are even more important in one particular type of SVector: the String, which is an SVector of chars. As a specialization of the SVector type, the String has all of the characteristics of any other SVector, but has additional abilities as well. Primary among these is its ability to be read or written using the standard C++ input/output stream functions. This String type, or one very much like it, is one of the most obvious improvements in C++ over C, whose corresponding char* type is notoriously error-prone. In this program, we will use the String data type in much the same way as we would use the char* data type in a C program. Unfortunately, we will not be able to go into detail on the implementation of either the SVector or String classes in this book; we will just use their facilities as described immediately above. A Very Useful typedef Another "type" used in this simple test program is ArrayIndex. This is also a typedef, but for a much simpler underlying type: unsigned long. In this case, the reason I didn't just use the underlying type was to enhance portability. The original version of this program was implemented on a 16-bit compiler, where the definition of ArrayIndex was unsigned short, primarily because it was impossible to create an array or SVector having more than 64K elements. When I ported this program to a 32-bit compiler, I changed the definition of ArrayIndex and several other similar typedefs and recompiled. I would like to be able to tell you that the program worked without further changes, but that would be a lie: it actually took me a couple of days to get it working again. However, considering the size of the source code for the classes (over 100KB), I was quite happy to take such a short time to port it. If I had used the explicit type unsigned short everywhere, it would have taken me much longer to figure out which occurrences of that type should be changed to unsigned long and which should remain as they were. As it was, I found a few places where I did not use a typedef or used the wrong one and ran into trouble as a result. Overall, though, I did a pretty good job in using appropriate types originally, which saved me a lot of trouble later. A Quantum Leap Now let's start our journey into the interior of the quantum file implementation, starting with the QuantumFile class itself, whose header file is shown in Figure blockh.00. Header file for QuantumFile class (quantum\block.h) (Figure blockh.00) codelist/blockh.00 I can't say that I'm completely happy with the design of this class. Ideally, the user of any class should not have to worry about any member data or member variables that the user cannot or should not use. Unfortunately, this is not easily accomplished in C++. I believe it is worthwhile to digress slightly here to discuss the reasons why this is so. First, let's examine the difficulty of "hiding" private and protected member variables from the class user. The technical problem here is that the compiler cannot allocate space for a variable unless its size is known. This implies that you cannot create a variable of a given class without access to its interface definition, which must in turn include the definitions of all of its member variables. This does not allow the class user to use those member variables unless they are public, so we don't have to worry about non-member functions accidentally altering member variables. However, it does mean that the user of a class must ensure that all of the data types needed in the declaration of a class are available when the header for that class is compiled, and that the names of those data types do not conflict with any previously defined names. This can be a source of considerable difficulty when trying to use a fairly large library in a context other than the one in which it was developed, which of course reduces the payoff that such reuse would otherwise provide. The other problem with the design of this class is that it defines a number of functions that application programmers have no need for. These functions are intended for use by other classes that contribute to the functionality of the quantum file implementation. You might think that I could simply make these functions private to prevent their being called by outside classes. Unfortunately, I wasn't able to do that with Microsoft Visual C++ 5.0, one of the compilers with which this code must work, as that compiler apparently cannot understand friend declarations . they may be stored in the same quantum file. In order to facilitate reconstruction of the file if part of the IRA is lost, we won't use the same quantum for items from two different arrays;. it has been created, by calling its resize member function. 4. You can assign one SVector of a particular type to another SVector of the same type. 5. You can create an SVector by copying from. these are very useful characteristics for any type of SVector, they are even more important in one particular type of SVector: the String, which is an SVector of chars. As a specialization of the

Ngày đăng: 06/07/2014, 03:20