Co do ostatniego problemu
dział:
porady
kursy praktyczne
Baza danych. Jest tam kod odpowiedzialny za wczytywanie danych z pliku tekstowego bezpośrednio do tabeli TStringGrid, a separator sobie ustawisz. Kod musisz oczywiście dostosować do własnych potrzeb.
Możesz również skorzystać z porady:
Zapisywanie i odczytywanie zawartości obiektu StringGrid. w dziale:
porady
StringGrid.
Zrobiłem jak w poradzie z tym, że mam błąd :
|
[Linker Error] Unresolved external 'TForm1::BubbleSort(Grids::TStringGrid *, int)' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\PROJECTS\STRIN GRID 2\UNIT1.OBJ |
Problem polega na tym, że nie zastosowałeś się do porady, czyli w poradzie funkcja
BubbleSort nie jest metodą klasy
TForm1, Ty natomiast chciałeś uczynić ją metodą klasy
TForm1 więc w pliku nagłówkowym
Unit1.h w sekcji
private dałeś:
private: // User declarations
void BubbleSort(TStringGrid *Tabela, int Col);
To, że chcesz uczynić tą funkcję metodą klasy
TForm1, żadnym błędem nie jest, ale Ty w pliku źródłowym tak zapiałeś tą funkcję:
void BubbleSort(TStringGrid *Tabela, int Col)
{
String temp;
for(int i = Tabela->FixedRows; i < Tabela->RowCount; i++)
{
for(int j = Tabela->FixedRows; j < i; j++)
{
if(Tabela->Cells[Col][i] < Tabela->Cells[Col][j])
{
temp = Tabela->Rows[i]->GetText();
Tabela->Rows[i]->SetText(Tabela->Rows[j]->GetText());
Tabela->Rows[j]->SetText(temp.c_str());
}
}
}
}
I tutaj jest problem, gdyż to nie czyni funkcji metodą klasy
TForm1, ponieważ masz tak:
void BubbleSort(TStringGrid *Tabela, int Col)
a powinno być tak:
void TForm1::BubbleSort(TStringGrid *Tabela, int Col)
czyli
TForm1::BubbleSort
Funkcje mam wywołać z nazwą StringGrida i numerem kolumn które chce posortować ?
To co zaproponował
polymorphism jest niemal identyczne z tym co ja proponuję w poradzie:
porady
StringGrid
Sortowanie tabeli StringGrid. Z tą różnicą, że proponowany przeze mnie kod jest przystosowany do sortowania tabeli
StringGrid dla wybranej kolumny. Sortowane są wszystkie wiersze w oparciu o sortowaną kolumnę, a więc powiązania komórek w wierszu pozostają, gdyż tak to powinno wyglądać. Sortowanie odbywa się tekstowo, czyli zawartość komórek traktowana jest jak tekst, a nie jak liczby, ale w poradzie: dział:
porady
ListBox
Sortowanie listy według różnych kryteriów (liczby lub tekstu), pokazany jest sposób sortowania również wg. liczby, wystarczy więc odpowiednie funkcje zaadoptować do potrzeb tabeli:
#pragma warn +csu
enum TTypeSort {tsIncrease, tsDecrease, tsIncreaseInt, tsDecreaseInt};
int foo(int u, int i) /* funkcja pomocnicza */
{
int z = u - i;
return z;
}
//---------------------------------------------------------------------------
int __fastcall CustomSortIncreaseInt(TStringList *Lista, int idx1, int idx2)
{ /* sortowanie rosnąco wg. liczb */
String cTemp1 = Lista->Strings[idx1];
String cTemp2 = Lista->Strings[idx2];
int x1 = cTemp1.Pos("^");
int x2 = cTemp2.Pos("^");
int rTemp1 = cTemp1.SubString(1, x1 - 1).Trim().ToIntDef(0);
int rTemp2 = cTemp2.SubString(1, x2 - 1).Trim().ToIntDef(0);
return foo(rTemp1, rTemp2);
}
//---------------------------------------------------------------------------
int __fastcall CustomSortDecreaseInt(TStringList *Lista, int idx1, int idx2)
{ /* sortowanie malejąco wg. liczb */
String cTemp1 = Lista->Strings[idx1];
String cTemp2 = Lista->Strings[idx2];
int x1 = cTemp1.Pos("^");
int x2 = cTemp2.Pos("^");
int rTemp1 = cTemp1.SubString(1, x1 - 1).Trim().ToIntDef(0);
int rTemp2 = cTemp2.SubString(1, x2 - 1).Trim().ToIntDef(0);
return -foo(rTemp1, rTemp2);
}
//---------------------------------------------------------------------------
int __fastcall CustomSortIncrease(TStringList *Lista, int idx1, int idx2)
{ /* sortowanie rosnąco wg. tekstu */
String cTemp1 = Lista->Strings[idx1];
String cTemp2 = Lista->Strings[idx2];
return CompareText(cTemp1, cTemp2);
}
//---------------------------------------------------------------------------
int __fastcall CustomSortDecrease(TStringList *Lista, int idx1, int idx2)
{ /* sortowanie malejąco wg. tekstu */
String cTemp1 = Lista->Strings[idx1];
String cTemp2 = Lista->Strings[idx2];
return -CompareText(cTemp1, cTemp2);
}
//---------------------------------------------------------------------------
void __fastcall SortGrid(TStringGrid *Grid, int Col, TTypeSort tsSort)
{ /* funckja sortująca */
TStringList *SortList = new TStringList;
String temp = "";
for(int i = Grid->FixedRows; i < Grid->RowCount; i++)
{
temp = Grid->Cells[Col][i];
if(temp.IsEmpty()) temp = " ";
for(int z = Grid->FixedCols; z <= Grid->ColCount; z++)
{
if(Grid->Cells[z][i].IsEmpty()) Grid->Cells[z][i] = " ";
if(z != Col)
temp = temp + "^" + Grid->Cells[z][i];
}
SortList->Add(temp.SubString(0, temp.Length() - 1));
temp = "";
}
switch(tsSort)
{
case tsIncrease: SortList->CustomSort(CustomSortIncrease); break;
case tsIncreaseInt: SortList->CustomSort(CustomSortIncreaseInt); break;
case tsDecrease: SortList->CustomSort(CustomSortDecrease); break;
case tsDecreaseInt: SortList->CustomSort(CustomSortDecreaseInt); break;
}
temp = "";
for(int i = 0; i < SortList->Count; i++)
{
temp = SortList->Strings[i];
int y = temp.Pos("^");
Grid->Cells[Col][i + 1] = temp.SubString(1, y - 1).Trim();
temp = temp.Delete(1, y);
int z;
for(z = Grid->FixedCols; z < Grid->ColCount; z++)
{
if(z != Col)
{
y = temp.Pos("^");
Grid->Cells[z][i + 1] = temp.SubString(1, y - 1).Trim();
temp = temp.Delete(1, y);
}
}
z++;
y = temp.Pos("^");
Grid->Cells[z][i + 1] = temp.SubString(1, y - 1).Trim();
temp = temp.Delete(1, y);
}
delete SortList;
}
//---------------------------------------------------------------------------
/* zdarzenie OnMouseDown - sortowanie po kliknięciu w kolumnę */
TTypeSort tsSwitch = tsIncreaseInt;
int sCol = -1, sRow = -1;
void __fastcall TForm2::StringGrid1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
TGridCoord mCoord = StringGrid1->MouseCoord(X, Y);
if(mCoord.Y == StringGrid1->FixedCols - 1)
{
sCol = mCoord.X;
StringGrid1->Col = sCol;
switch(tsSwitch)
{
case tsIncreaseInt: SortGrid(StringGrid1, sCol, tsSwitch);
tsSwitch = tsDecreaseInt;
StringGrid1->Repaint();
return;
case tsDecreaseInt: SortGrid(StringGrid1, sCol, tsSwitch);
tsSwitch = tsIncreaseInt;
StringGrid1->Repaint();
return;
}
}
}
//---------------------------------------------------------------------------
/* zdadzenie OnDrawCell - rysowanie strzałki określajacej kierunek sortowania */
void __fastcall TForm2::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow,
TRect &Rect, TGridDrawState State)
{
if(ACol == sCol)
{
TRect rRect = StringGrid1->CellRect(sCol, 0);
StringGrid1->Canvas->Brush->Color = clBlack;
StringGrid1->Canvas->Pen->Color = clBlack;
switch(tsSwitch)
{
case tsIncreaseInt:
StringGrid1->Canvas->Polygon(OPENARRAY (TPoint, (
Point(rRect.Right - 10, rRect.Top + 5),
Point(rRect.Right - 13, rRect.Top + 10),
Point(rRect.Right - 8, rRect.Top + 10)
)));
break;
case tsDecreaseInt:
StringGrid1->Canvas->Polygon(OPENARRAY (TPoint, (
Point(rRect.Right - 13, rRect.Top + 5),
Point(rRect.Right - 10, rRect.Top + 10),
Point(rRect.Right - 8, rRect.Top + 5)
)));
break;
}
}
}
Gdybyś chciał posortować wybraną kolumnę klikając np. na przycisku
Button1 to wystarczy funkcji
SortGrid przekazać jako pierwszy argument wskaźnik na obiekt, który ma być sortowany, jako drugi argument kolumna w oparciu o którą cała tabela będzie sortowana, a jako trzeci argument sposób sortowania:
void __fastcall TForm2::Button1Click(TObject *Sender)
{ /* sortowanie rosnąco wegług liczb */
SortGrid(StringGrid1, 1, tsIncreaseInt);
}
Sortowanie na cztery sposoby:
- tsIncrease - zawartość komórek traktowana tylko jako tekst - sortowanie rosnąco
- tsDecrease - zawartość komórek traktowana tylko jako tekst - sortowanie malejąco
- tsIncreaseInt - zawartość komórek traktowana najpierw jako liczby, potem jako tekst o ile zawierają wartości nie będące liczbą - sortowanie rosnąco
- tsDecreaseInt - zawartość komórek traktowana najpierw jako liczby, potem jako tekst o ile zawierają wartości nie będące liczbą - sortowanie malejąco