Wyszukiwanie rekordów

dział ogólny

Wyszukiwanie rekordów

Nowy postprzez Bert1223 » środa, 17 marca 2010, 01:52

Witam, głowie się już pół nocy nad skuteczną metodą wyszukiwania ale puki co nie dział to tak jak ma.
Prosiłbym o przeanalizowanie proponowanych prze zemnie rozwiązań, podpowiedzenie co jest nie tak, czy zasugerowanie całkiem innego pomysłu.
Kod: Zaznacz cały
   // Jakie pola przeszukiwać
   int szukaj[7] = {0, 0, 0, 0, 0, 0, 0};
   // Indexy dla poszczególnych przeszukiwanych pół
   int index[8] = {0, 0, 0, 0, 0, 0, 0, 0};

   // Tablica dla znalezionych produktów w poszczególnych polach
   int tab[7][5000];
   for(int i = 0; i < 7; i++)
      for(int j = 0; j < 5000; j++)
         tab[i][j] = 0;

   // Końcowa tablica
   int finish[5000];
   for(int i = 0; i < 5000; i++)
      finish[i] = 0;

   // Sprawdzenie kryteriów wyszukiwania
   if(ComboBox1->Text != "")
      szukaj[0] = 1;
   if(ComboBox2->Text != "")
      szukaj[1] = 1;
   if(ComboBox3->Text != "")
      szukaj[2] = 1;
   if(Edit1->Text != "")
      szukaj[3] = 1;
   if(Edit2->Text != "")
      szukaj[4] = 1;
   if(Edit3->Text != "")
      szukaj[5] = 1;

   // Po tej operacji wiemy po jakich polach nasz użytkownik chce wyszukiwać.

   // Zmienna flagowa do sprawdzenia czy sa jakie kolwiek kryteria wyszukiwania.
   bool ok = 0;

   // Zmienna zliczająca ilośc kryteriów wyszukiwania
   int ile = 0;

   // Sprawdzenie kryteriów wyszukiwania
   for(int i = 0; i < 7; i++)
   {
      if(szukaj[i] )
      {
         ok = 1;
         ile++;
      }
   }

   if(ok)
   {
      int i = 0;
      while(Produkt[i].getId())
      {
         // Wyszukanie produktów odpowiadającym - Dystrybutowi
         if(szukaj[0])
            if(ComboBox1->Text == Produkt[i].getDystrybutor())
            {
               tab[0][index[0]] = Produkt[i].getId();
               index[0]++;
            }

         // Wyszukanie produktów odpowiadającym - Producentowi
         if(szukaj[1])
            if(ComboBox2->Text == Produkt[i].getProducent())
            {
               tab[1][index[1]] = Produkt[i].getId();
               index[1]++;
            }

         // Wyszukanie produktów odpowiadającym - Typ
         if(szukaj[2])
            if(ComboBox3->Text == Produkt[i].getTyp())
            {
               tab[2][index[2]] = Produkt[i].getId();
               index[2]++;
            }

         //... i tak dla pozostałych 3
         //...
         //...

         i++;
      }
   }
   else
   {
      ShowWindowError("Nie wprowadzono kryteriów wyszukiwania!");
   }

   // Uzupełnienie tabeli finish dla 1 kryterium
   if(ile == 1)
   {
      // Pętla - w celu znaleziania dla którego kryterium przeprowadzono wyszukiwanie
      for(int i = 0; i < 7; i++)
      {
         if(szukaj[i])
         {
            for(int j = 0; j < index[i]; j++)
            {
               finish[j] = tab[i][j];
               index[7]++;
            }

            // Zakończenie uzupełniania tabeli finish
            break;
         }
      }
   }

   if(ile > 1)
   {
      // Zmienna sprawdzająca czy jest to pierwsze przejście pętli      
      bool first = 0;

      for(int m = 0; m < 7; m++)
      {
         if(!first)
         {
            for(int n = 0; n < index[m]; n++)
            {
               finish[n] = tab[m][n];
               index[7]++;
            }

            first = 1;
         }
         else
         {
            // Tablica przetrzymująca wynik z następnego wiersza i finish            
            int found[5000];
            for(int i = 0; i < 5000; i++)
               found[i] = 0;

            // Index dla tablicy found
            int index_found = 0;

            for(int n = 0; n < index[7]; n++)
            {
               for(int i = 0; i < index[m]; i++)
               {
                  int x = finish[n];
                  int y = tab[index[m]][i];
                  if(finish[n] == tab[index[m]][i])
                  {
                     found[index_found] = finish[n];
                     index_found++;
                  }
                   }

            for(int i = 0; i < index[7]; i++)
               finish[i] = 0;
            index[7] = 0;

            for(int i = 0; i < index_found; i++)
               finish[i] = found[i];
         }
      }
   }

   if(ok)
   {
      ListView1->Clear();

      for(int i = 0; i < index[7]; i++)
      {

         int id = 0;
         while( Produkt[id].getId() )
         {
            if(Produkt[id].getId() == finish[i])
            {
               TListItem * item;
               item = ListView1->Items->Add();

               item->Caption = AnsiString( Produkt[ id ].getDystrybutor() );
               item->SubItems->Add( Produkt[ id ].getProducent() );
               item->SubItems->Add( Produkt[ id ].getTyp() );
               item->SubItems->Add( Produkt[ id ].getFaktura() );
               item->SubItems->Add( Produkt[ id ].getKod() );
               item->SubItems->Add( Produkt[ id ].getSterial() );
               item->SubItems->Add( Produkt[ id ].getGwarancja() );
               item->SubItems->Add( Produkt[ id ].getData() );
               item->SubItems->Add( Produkt[ id ].getIlosc() );
               item->SubItems->Add( Produkt[ id ].getInfo() );
               item->SubItems->Add( Produkt[ id ].getId() );

               bool icon = 0;
               if(Produkt[ id ].getTyp() == "Karta sieciowa")
               {
                  item->ImageIndex = 1;
                  icon = 1;
               }

               if(!icon)
               {
                  item->ImageIndex = 0;
               }
            }

            id++;
         }
      }
   }


Algorytm działa poprawnie tylko dla 1 kryterium.
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Wyszukiwanie rekordów

Nowy postprzez Cyfrowy Baron » środa, 17 marca 2010, 08:22

Strasznie to wszystko zagmatwane. Tyle tablic... czy rzeczywiście tyle tablic potrzeba?! Mieszasz zmienne typu bolean z typem integer przez co kod staje się jeszcze bardziej nieczytelny. Zacząłem go analizować, ale gdy doszedłem do połowy to już się pogubiłem.

Zawarłeś wszystko w jednej funkcji zamiast stworzyć odrębną funkcje wyszukującą, której zadasz kryterium wyszukiwania, a ona to przeszuka.



Po co tak:

Kod: Zaznacz cały
   int szukaj[7] = {0, 0, 0, 0, 0, 0, 0};
 
   // ...
 
   if(ComboBox1->Text != "")
      szukaj[0] = 1;
   if(ComboBox2->Text != "")
      szukaj[1] = 1;

  //...

  if(szukaj[0])
   if(ComboBox1->Text == Produkt[i].getDystrybutor())
   {
     tab[0][index[0]] = Produkt[i].getId();
     index[0]++;
   }

   // Wyszukanie produktów odpowiadającym - Producentowi
   if(szukaj[1])
     if(ComboBox2->Text == Produkt[i].getProducent())
     {
      tab[1][index[1]] = Produkt[i].getId();
      index[1]++;
     } 


Skoro prościej i czytelniej będzie tak:


Kod: Zaznacz cały
if(ok)
{
  int i = 0;
  bool liczile = true;
  while(Produkt[i].getId())
{
   if(!ComboBox1->Text.IsEmpty() && ComboBox1->Text == Produkt[i].getDystrybutor())
   {
     tab[0][index[0]] = Produkt[i].getId();
     index[0]++;
     if(liczile) ile += 1;
   }

   // Wyszukanie produktów odpowiadającym - Producentowi
   if(!ComboBox2->Text.IsEmpty() && ComboBox2->Text == Produkt[i].getProducent())
   {
     tab[1][index[1]] = Produkt[i].getId();
     index[1]++;
     if(liczile) ile += 1;
   } 
 
  //...
  i++;
  liczile = false;
}


Ze zmienną ok też można poradzić sobie prościej:

Kod: Zaznacz cały
  if(!ComboBox1->Text.IsEmpty() || !ComboBox2->Text.IsEmpty() || !ComboBox2->Text.IsEmpty() ||
      !Edit2->Text.IsEmpty() || !Edit2->Text.IsEmpty() || !Edit2->Text.IsEmpty())
    ok = true;
  else
    ok = false;


Tak jest szybciej, gdyż pętla Sprawdzanie kryteriów wyszukiwania jest zbędna, więc kod działa szybciej.

Trzeba by jednak przemyśleć od początku kod Uzupełnienie tabeli finish dla 1 kryterium, gdyż teraz przestanie działać. Panuje tam jednak już taki chaos, że trudno się połapać.
Dobrym rozwiązaniem byłoby stworzenie odrębnej funkcji dla tego kodu.

Przemyśl to jeszcze raz. Podziel dok an części w odrębnych funkcjach. Jak zoptymalizujesz, to być może znajdziesz przyczynę błędu, gdyż diabeł zawsze tkwi w szczegółach.



Czy na pewno chodzi o:

if(ComboBox->Text != "") // prostszy zapis: if(!ComboBox->Text.IsEmpty())

Co oznacza, że właściwość Text obiektu ComboBox nie jest pusta, przecież lista może być pełna a wartość Text może być pusta, a tutaj jak sądzę chodzi o sprawdzenie czy lista zawiera jakieś elementy, czyli lepszym rozwiązaniem byłoby sprawdzić czy lista nie jest pusta:

if(CombBox->Items->Count > 0)

Chyba, że chodzi o sprawdzenie, czy nie wybrano jakiegoś elementu z listy, wtedy należałoby zrobić to raczej tak:

if(ComboBox->ItemIndex != -1)
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Wyszukiwanie rekordów

Nowy postprzez polymorphism » środa, 17 marca 2010, 10:38

Z tym kodem Bert pojechałeś ;) Przecież można tak:
Kod: Zaznacz cały
vector<int> found;
unsigned   what = 0;

if(!ComboBox1->Text.IsEmpty())what = 1;
if(!ComboBox2->Text .IsEmpty())what = 2;
if(!ComboBox3->Text.IsEmpty())what = 4;
if(!Edit1->Text .IsEmpty())what = 8;
if(!Edit2->Text.IsEmpty())what = 16;
if(!Edit3->Text.IsEmpty())what = 32;

if(what == 0)
{
   ShowWindowError("Nie wprowadzono kryteriów wyszukiwania!");
   /* tu (chyba) powinien być wyskok z funkcji */
}

for(int i = 0; Produkt[i].getId(); ++i)
{
   bool ok = false;
   ok |= (what & 1 && ComboBox1->Text == Produkt[i].getDystrybutor());
   ok |= (what & 2 && ComboBox2->Text == Produkt[i].getProducent());

   //itd.
   
   if(ok) found.push_back(Produkt[i].getId());
}

found zawiera id znalezionych produktów. Zamiast liczb 1,2,4,8, itd. powinien być użyty bardziej opisowy typ wyliczeniowy (enum).

___
p.s. nie wiem co tam dalej się dzieje w tym Twoim spaghetti kodzie, ale myślę, że kod, który podałem, powinien Ciebie naprowadzić na bardziej racjonalny sposób realizacji wyszukiwania.



Baron, a próbowałeś instalować GeSHi?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Wyszukiwanie rekordów

Nowy postprzez Bert1223 » piątek, 19 marca 2010, 16:09

Póki co to kod zostawiam w tej formie, a algorytm poprawiłem.
Kod: Zaznacz cały
   if(ile > 1)
   {
      bool first = 0;

      // Pętla w celu znaleziania dla którego kryterium przeprowadzono wyszukiwanie
      for(int i = 0; i < 7; i++)
      {
         if(szukaj[i])
         {
            if(!first)
            {
               for(int n = 0; n < index[i]; n++)
               {
                  finish[n] = tab[i][n];
                  index[7]++;
               }

               first = 1;
            }
            else
            {
               for(int n = 0; n < index[7]; n++)
               {
                  bool jest = 0;
                  // przegladanie elementów z finish

                  for(int m = 0; m < index[i]; m++)
                  {
                  // przegladanie elementów z tablicy i
                     if(finish[n] == tab[i][m])
                        jest = 1;
                  }

                  if(jest == 0)
                  {
                     finish[n] = 0;
                  }
               }
            }
         }
      }
   }
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości