
Опытный
 
Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев
Репутация: 9 Всего: 23
|
у мя щас под рукой Builder нет, но помойму тут предельно ясно написано, что нуно сделать и как Код | Sorting a TList by Kent Reisdorph
The TList class is great for storing objects of any type. You can store structures, classes, integers, doubles, and well, just about any type of data. Frequently, you may need a sorted list; TList has a Sort method that allows you to sort the list. Unfortunately, the Sort method is a bit confusing at first and often misunderstood. In this article, we'll show you how to use the Sort method to sort your lists, no matter what they contain.
The Sort method You use the Sort method of TList to sort the list. That's not too surprising, is it? The declaration for Sort looks like this: void __fastcall Sort(TListSort Compare Compare); The single parameter for the Sort method is a pointer to a comparison function, which will be called for every item in the list. We'll talk more about the comparison function in a minute.
Once you've created a comparison function, you can call Sort with the following lines:
TList* list = new TList; // Add some items to the list. list->Sort(Comparison Function); Believe it or not, that's all there is to calling the Sort method. Obviously, there must be more to calling Sort than these few lines of code. There is, of course, so let's examine the comparison function. Then we'll return to the Sort method.
The comparison function The comparison function does all of the work of sorting the list. It accepts two items from the list and returns a value. The comparison function must be of type TListSortCompare, which is declared as follows: typedef int __fastcall (*TListSortCompare) (void * Item1, void * Item2); That declaration might not mean much to you, so let me clarify a bit. The comparison function follows a specific function signature. Here's a sample declaration for a comparison function: int __fastcall Sorter(void* Item1, void* Item2); As you can see, the function has two parameters. The two parameters are pointers to two of the objects in the list. (It doesn't matter to you which two items in the list are being passed in, just how you compare the two.)
Notice that both parameters are void pointers. Since a TList just stores a list of pointers, that's exactly what you get in the comparison function. Put another way, TList doesn't know what it contains, so it just gives you two pointers and leaves it up to you to decide what to do with them. You'll cast the void pointers to something useful, compare the two items, then return a value based on the comparison.
The comparison function must be either a regular function or, if the function is a member of a class, it must be declared as static. The easiest approach is to just make it a regular function. Sorting simple data The value returned from the comparison function determines how the list is sorted. Table A shows what you should return from the comparison function.
Table A: Return value from the comparison function.Condition Return Value Item1 = Item2 0 Item1 > Item2 Any positive number Item1 < Item2 Any negative number
We'll look at a simple example to illustrate the point. Let's say you had a list of integers that you wanted to sort. In that case, the comparison function would look like this:
int __fastcall SortInt void* Item1, void* Item2) { int X1 = (int)Item1; int X2 = (int)Item2; return X1 - X2; } Because the list contains integers, we must cast the void pointers to an int to get the actual value of the item. (As I've said in past articles, I'm a big fan of the C++ casting operators over the old C-style casts. However, in this case, you don't gain anything by using the C++ casting operator, static_cast, so the C-style cast is perfectly acceptable.)
Now look at the return statement in this function. If X1 is greater than X2, then a positive value will be returned. If X1 is less than X2, then the return statement produces a negative value. When X1 and X2 are equal, the return value is 0: A single statement takes care of it all.
This one statement sorts the list of integers in ascending order. But what if you want to sort the integers in descending order? Not a problem; just reverse the variables in the return statement:
return X2 - X1; The list is now sorted in descending order. To sort the list in either ascending or descending order, you'll have to use two separate comparison functions (or implement a global variable that holds the sort direction).
Sorting complex objects You can sort complex objects as well as simple objects. For example, you may have a list of classes that you want to sort. In that case, the sort is only slightly more complex than it would be if you were sorting integral data types. So what do you use as a sort criteria when sorting classes? That's up to you. Since you know what your class contains, you can sort it in any way you like.
Let me give you an example of a class that contains an integer data member. First, we'll look at this class:
class MyNumberClass { public: MyNumberClass(int data) { Data = data; } int Data; // More of the class here. }; Now, let's say you had a list of MyNumberClass objects. To sort the list in ascending order, you'd write a comparison function like this:
int __fastcall IntSort (void* Item1, void* Item2) { MyNumberClass* MC1 = (MyNumberClass*)Item1; MyNumberClass* MC2 = (MyNumberClass*)Item2; return MC1->Data - MC2->Data; } Notice that this function differs only slightly from the integer sorting function you saw earlier. First, the void pointers are cast to MyNumberClass pointers, then the Data member of the two objects is used to perform the comparison. Similarly, if you had a class that contained an AnsiString data member, you could sort the list like this: int __fastcall StrSort (void* Item1, void* Item2) { MyStringClass* MS1 = (MyStringClass*)Item1; MyStringClass* MS2 = (MyStringClass*)Item2; return MS1->Text.AnsiCompare (MS2->Text); } Although these are pretty simple cases, my point is that you can sort any type of object --in any way you wish. Deciding how the objects should be sorted is completely up to you. All you have to do is return 0, a positive number, or a negative number from the comparison routine.
Listing A contains the main form unit of a program that demonstrates sorting TList container classes. The program sorts two types of classes: one by an integer value and the other according to a string data member. (We are showing only the CPP file. The header is all C++Builder-generated, so there's no point in showing it here.)
The program's main form contains two buttons. The first button sorts the list of integer-based classes, and the second button sorts a list of string-based classes. Both ascending and descending sorting routines are provided. The results of the sort are displayed in a memo, so you can see the result.
To create this program, place a Memo component and two buttons on a form. Then enter the code below. Alternatively, you can download the code from our Web site at www.cobb.com/cpb ; click on the Source Code hyperlink.
Listing A: LISTSORT.CPP //------------------------- \ -------------------- #include <vcl.h> #pragma hdrstop
#include "SortU.h" //------------------------- -------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //------------------------- -------------------- __fastcall TForm1::TForm1 (TComponent* Owner) : TForm(Owner) { } //------------------------- --------------------
// A class that contains an int data member. class MyNumberClass { public: MyNumberClass(int data) { Data = data; } int Data; };
// A class that contains a String data member. class MyStringClass { public: MyStringClass(String text) { Text = text; } String Text; };
// The ascending sort function for MyNumberClass. int __fastcall SortAscending(void* Item1, void* Item2) { MyNumberClass* MC1 = (MyNumberClass*)Item1; MyNumberClass* MC2 = (MyNumberClass*)Item2; return MC1->Data - MC2->Data; }
// The descending sort function for MyNumberClass. int __fastcall SortDescending(void* Item1, void* Item2) { MyNumberClass* MC1 = (MyNumberClass*)Item1; MyNumberClass* MC2 = (MyNumberClass*)Item2; return MC2->Data - MC1->Data; }
// The ascending string sort function // for MyStringClass. int __fastcall StringSortAscending (void* Item1, void* Item2) { MyStringClass* MS1 = (MyStringClass*)Item1; MyStringClass* MS2 = (MyStringClass*)Item2; return MS1->Text.AnsiCompare (MS2->Text); }
// The descending string sort function // for MyStringClass. int __fastcall StringSortDescending (void* Item1, void* Item2) { MyStringClass* MS1 = (MyStringClass*)Item1; MyStringClass* MS2 = (MyStringClass*)Item2; return MS2->Text.AnsiCompare (MS1->Text); }
void __fastcall TForm1::Button1Click(TObject *Sender) { // Create a TList and fill it with instances // of the MyNumberClass class. TList* list = new TList; list->Add(new MyNumberClass(100)); list->Add(new MyNumberClass(1)); list->Add(new MyNumberClass(23)); list->Add(new MyNumberClass(54)); list->Add(new MyNumberClass(77)); list->Add(new MyNumberClass(89)); list->Add(new MyNumberClass(12)); list->Add(new MyNumberClass(17)); list->Add(new MyNumberClass(22)); list->Add(new MyNumberClass(94)); list->Add(new MyNumberClass(87)); list->Add(new MyNumberClass(55)); list->Add(new MyNumberClass(33)); list->Add(new MyNumberClass(62));
// Sort the list in ascending order and // display the results in the memo. list->Sort(SortAscending); Memo1->Text = "Ascending Sort"; for (int i=0;i<list->Count;i++) { MyNumberClass* mc = (MyNumberClass*)list->Items[i]; Memo1->Lines->Add("Item " + String(i) + ": " + String (mc->Data)); } Memo1->Lines->Add(""); Memo1->Lines->Add("");
// Sort the list in descending order and // display the results in the memo. list->Sort(SortDescending); Memo1->Lines->Add ("Descending Sort"); for (int i=0;i<list->Count;i++) { MyNumberClass* mc = (MyNumberClass*)list->Items[i]; Memo1->Lines->Add("Item " + String(i) + ": " + String (mc->Data)); } for (int i=0;i<list->Count;i++) { MyNumberClass* mc = (MyNumberClass*)list->Items[i]; delete mc; } delete list; } //------------------------- -------------------- void __fastcall TForm1::Button2Click (TObject *Sender) { // Create a TList and fill it with instances // of the MyNumberClass class. TList* list = new TList; list->Add(new MyStringClass ("Hello there!")); list->Add(new MyStringClass ("What's going on?")); list->Add(new MyStringClass ("This is a test.")); list->Add(new MyStringClass ("Nothing new here!")); list->Add(new MyStringClass ("TurboPower Software")); list->Add(new MyStringClass ("Borland International")); list->Add(new MyStringClass( "A short string.")); list->Add(new MyStringClass ("Hello again!")); list->Add(new MyStringClass(22)); list->Add(new MyStringClass(94)); list->Sort(StringSortAscending);
// Sort the list in ascending order and // display the results in the memo. Memo1->Text = "Ascending Sort"; for (int i=0;i<list->Count;i++) { MyStringClass* mc = (MyStringClass*)list->Items[i]; Memo1->Lines->Add(mc->Text); } Memo1->Lines->Add(""); Memo1->Lines->Add("");
// Sort the list in descending order and // display the results in the memo. list->Sort(StringSortDescending); Memo1->Lines->Add ("Descending Sort"); for (int i=0;i<list->Count;i++) { MyStringClass* mc = (MyStringClass*)list->Items[i]; Memo1->Lines->Add(mc->Text); }
// Delete all the objects and then // delete the list itself. for (int i=0;i<list->Count;i++) { MyStringClass* mc = (MyStringClass*)list->Items[i]; delete mc; } delete list; } |
сомнееваюсь, что офдоки сильно отличаются
--------------------
Имеющий язык - да не убоится спросить! 
|