Algorytm zastepowania tekstu * (gwiazdkami)

0

Witam!
Potrzebuje jak ort! algorytm porownywania dwoch stringow. Jeden jest zwyklym tekstem (np. "Ala ma kota") drugi zawiera gwiazdki ktore moga zastapic dowolny ciag znakow, w dowolnej ilosci tych gwiazdek np. ("Almaa"). W przykladzie oczywiscie oba stringi sie zgadzaja (gwiazdka zastepuje rowniez spacje).

  1. Mogl by mi ktos podac ten algorytm?
  2. Czy da sie to napisac bez rekurencji?

Pozdrawiam,
I z gory dziekuje za odpowiedzi
Mupet

0
Function SamSeJaNazwij(t1, t2: string): Boolean;
const
	gw: char = '*';
Var
  i: integer;
Begin
  {Nie jest to konieczne jezeli wiesz ze maja identyczne dlugosci
  if Length(t1) <> Length(t2) then
    Begin
      Result := False;
      exit;
    End;}
  for i := 1 to Length(t1) do
    Result := (t2[i] = gw) or (t1[i] = t2[i]);
End;
0

Problem w tym, że to nie zadziała. Działałoby, gdyby * zastępowała JEDNĄ literkę, a ona ma zastępować dowolny ciąg znaków. Patrz: przykład (długości są różne, a stringi się zgadzają). Osobiście mi za bardzo nic konkretnego do głowy nie przychodzi, ale może coś z Pos i Copy? Sam nie wiem...

0

Nie jest to dopracowane, bo nie chce mi się już myśleć, ale generalnie kod robi to co chciałeś:

var
  Form1: TForm1;
  wyraz:string;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var s:string;
    i,j,k:integer;
    x:array of string;
    CzyRowne: Boolean;
begin
  s:=Edit1.Text;
  wyraz:=Edit2.Text;
  i:=0;k:=0;
  SetLength(x,i+1);
  for j:=1 to length(s) do               //rozdzielanie wyrazu na tablice ze względu na gwiazdki
    begin
      if (s[j]<>'*') then x[i]:=x[i]+s[j]
        else
          begin
            Inc(i);
            SetLength(x,i+1);
          end;
    end;

   for j:=0 to i do   //wyszukiwanie kolejnych ciągów w wyrazie
    begin
      k:=(PosEx(x[j],wyraz,k));
      if k>0 then CzyRowne:=True else
        begin
          CzyRowne:=False;
          break;
        end;

    end;
  if CzyRowne then showmessage('podana recepta pasuje do wyrazu')
    else showmessage('niestety, wyraz nie pasuje do schematu');
end;

end.

na forme trzeba dodać:
Edit1: tu wpisujesz wyrażenie z gwaiazdkami
Edit2: tu sprawdzany wyraz
no i button żeby sobie ponaciskać :)

0

Dzieki wielkie za odpowiedzi(i), ale mam pytanko. Moze to ja jestem jakis niekumaty ale co to jest k:=(PosEx(x[j],wyraz,k)); ?
Chodzi mi o funkcjie PosEx, ja jej nie mam. W jakim ona powinna byc module?

0

Funkcja PosEx znajduje się w module systemowym, ale w Delphi 7. Działa ona tak samo jak Pos, z tą różnicą, że rozpoczyna wyszukiwanie od pewnego indeksu.

0

Zapomniałem dodać że do listy uses trzeba dodać StrUtils, no ale tego można się dowiedzieć naciskając F1 na danym słowie.

0

Sorry Panowie ale mam D6, i nie mam funkcji PosEx :(( (nawet po dodaniu StrUtils). Macie jakis pomysl co z tym zrobic ??
To mi naprawde potrzebne :> pliss
Pozdrawiam,
Mupet

0

Jesli dobrze zrozumialem co robi funkcja PosEx, to zamienilem ja na funkcje Pos.w nastepujacy spsosob :
Tutaj orginalny fragment :

  k:=(PosEx(x[j],wyraz,k));

A tutaj zamieniony przeze mnie:

   wyraz2:='';
  for y:=k to length(wyraz)do
    wyraz2:=wyraz2+wyraz[y];
    wyraz:=wyraz2;
  k:=(Pos(x[j],wyraz));

Moze niezbyt profesjonalnie ale chcialem tak byle dzialalo.Dodalem oczywiscie 2 zmienne y:integer i wyraz2:string;

Odpalam programik, ale wysypuje sie juz przy najprostrzych przykladach. Oto jeden z nich

edit1 "ala*a"
edit2 "alam"

Otrzymuje odpowiedz ze sie zgadza...

Kto mi pomoze szanowni koledzy :) ?

Pozdrawiam,
Mupet

0

Zawsze możesz ją napisać :). Wyglądałoby to mniej więcej tak (Piszę z pamięci, więc sprawdź, czy działa jak należy!):

function PosEx(SubStr, Str: String, PosStart: Integer): Integer;
begin
  if Pos(SubStr, copy(Str, PosStart, Length(Str)-PosStart+1))=0 then Result:=0
  else Result:=Pos(SubStr, copy(Str, PosStart, Length(Str)-PosStart+1))+PosStart-1;
  end;

P.S. W tamtym kodzie powyżej jest błąd... poza tym to naprawdę niewygodne rozwiązanie... Mam na myśli zastąpienie PosEx tym, co zaproponowałeś.

0

Dodalem funkcje PosEx napisana przez Ciebie
ale teraz program sie wywala rowniez przy najprostrzych przykladach. np:

edit1 ala*a
edit2 alaaa

Wyskakuje, ze sie nie zgadzaja :(
Jakies pomysly?

Pozdrawiam,
Mupet

0

Hmm... Rzeczywiście nie działa jak należy... Ale to chyba już nie wina mojej funkcji, tylko tego kodu wcześniej...

0

Przyznaje że mój kod nie jest profesjonanlny, bo progrmowaniem nie zajmuję się zbyt długo. Sam nie wiem jak można zastapiś funkcję PosEx w d6. Jedyne co proponuje to wstawić zwykłe Pos, tylko wtedy 12 będzie znaczyło to samo co 21 :|

0

Endrique, kolega Adam napisal funkcje PosEx. W Twoim kodzie musi byc blad ;(
Panowie programisci, czy naprawde nikt nie ma tego algorytmu - dzialajacego ?

0

Chyba, że źle zrozumiałem działanie funkcji PosEx. Niech ktoś z posiadaczy D7 poda mi wynik standardowego np. dla PosEx('abc', 'adam abc nic', 3);, a zobaczę, czy to nie u mnie jest błąd.

// 6 - ŁF

0

Chyba, że źle zrozumiałem działanie funkcji PosEx. Niech ktoś z posiadaczy D7 poda mi wynik standardowego np. dla PosEx('abc', 'adam abc nic', 3);, a zobaczę, czy to nie u mnie jest błąd.

6

skladnia jest taka - substr:stiring; s:string ; offset:cardinal=1 - offset podaje funkcji od ktorego miejsca w stringu S ma rozpoczac szukanie SubStr.

0

Pisalem bez wiekszego zastanowienia, ale przeszedl kilka testow i wyglada ze robi to co ma robic.

#include <iostream>
#include <cstring>

using namespace std;

bool czy_rowne(const char *, const char *);

int main()
{
  if ( czy_rowne("ala ma kota", "ala*ma*ta") )
   cout << "Rowne\n";
  else
   cout << "Nie rowne\n";
  cin.get();
}

bool czy_rowne(const char *S1, const char *S2)
{
  bool znalazl = false;
  for (int i = 0; i < (strlen(S2) + 1); i++)
   switch (S2[i])
   {
     case '*':
       if ( i == (strlen(S2) - 1) )
        return true;
       for (int j = i + 1; j < strlen(S1); j++)
        if ( (S2[i + 1] == S1[j]) && (znalazl = czy_rowne(S1 + j, S2 + i + 1)) )
         return true;
       if (!znalazl)
        return false;
       break;
     default:
       if (S2[i] != S1[i])
        return false;
   }
  return true;
}

I pewnie jak zauwazyles, nie jest w Pascalu, ale algorytm to algorytm. [diabel]

0

szkoda ze C++ to nie Delphi :-[

0

szkoda ze C++ to nie Delphi :-[

Szkoda, że nie jesteś myślącym programistą z umiejętnością myślenia abstrakcyjnego, bo wtedy po poświęceniu 10 minut miałbyś swoją wersję w Delphi.

0

Ja tez zaluje. Jedyne co mi sie udalo zmontowac z tego kodu to takie cos

function czy_rowne(var S1,s2:string):boolean;
var
   i,j:integer;
   znalazl:boolean;
begin
  znalazl:= false;
  for i:= 0 to (length(S2) + 1) do
{     switch (S2[i])}
   begin
{     case '*';   }
       if ( i =(length(S2) - 1) ) then czy_rowne:=true;
       for j:=i+1 to length(S1) do
        if ( (S2[i + 1] = S1[j]) and (znalazl = czy_rowne(S1 + j, S2 + i + 1)) )
          czy_rowne:=true;
       if znalazl=false then czy_rowne:=false;
       break;
{     default:}
       if (S2[i] <> S1[i])
        czy_rowne:=false;
   end;
   czy_rowne:=true;
end;

Tyle ze oczywiscie nie dziala (czesci sa pokomentowane itd.)

0

No jeżeli Twoja znajomośc Delphi jast taka jak to powyższe tłumaczenie to odsyłam do jakiegoś kursu, których na tej stronie nie brakuje.
Nawiasem mówiąc sprawdziłem działanie mojego kodu z 1 strony + to co Adam.P napisał i wydaje się być wszystko O.K. a czemu u Ciebie nie działa? zapewne odpowiedź znajdziesz w kursie!

0

chcialem sie zapytac co w C oznacza (S1 + j, S2 + i + 1)?? bardzo mnie to ciekawi i nie wiem jak to przekonwertowac na delphi. Bo string i integer nie dadza sie dodac.

//dopisane
//juz niewazne to wyzej

PROSZE PANSTWA - ZROBIONE (przerobione z algorymtmu foflika) - tak jestem az tak uczynny :)
OTO I KOD:

function czy_rowne(s1:string;s2:string):boolean;
var i:integer;j:integer; wynik:boolean;wynik2:boolean;
begin
wynik:=true;
i:=1;
while i<=length(s2) do
  begin
    case ord(s2[i]) of
    ord('*'): begin
                if i=length(s2)-1 then
                 wynik:=true;
              for j:=i+1 to length(s1) do
              begin
                if ((S2[i+1]=s1[j]) and (czy_rowne(copy(s1,j,length(s1)),copy(s2,i+ 1,length(s2))))) then
                begin
                  wynik:=true;
                  i:=j;
                end;
              end;
              end;
   else if (s2[i] <> s1[i]) then
   wynik:=false;
end;
if wynik=false then begin result:=czy_rowne(s1[i],s2[i+1]);exit;end;
inc(i);
end;
result:=wynik;
end;
0

Czyli moja funkcja PosEx jest prawidłowa. Problem w tym, ze jak ją u siebie dodam do kodu z początku (no... prawie początku), to nie działa prawidłowo. Natomiast to tłumaczenie, to raczej brak znajomości C, nie Pascala/Delphi. { to w C odpowiednik begin, a } - odpowiednik end. Taka mała wskazówka.

0

zdaje mie sie ze to juz bedzie EOT; kod wyzej.

//czyli !EOT :)

0

chcialem sie zapytac co w C oznacza (S1 + j, S2 + i + 1)?? bardzo mnie to ciekawi i nie wiem jak to przekonwertowac na delphi. Bo string i integer nie dadza sie dodac.

To ja już tak tylko gwoli jasności umysłów :)
S1 to nie string - to wskaźnik na pierwszy znak w nim. Więc np. S1+2 to wskazanie na 3 znak w ciągu - teraz już chyba wsio jasne. Taki OT.

0

Problem niestety nie rozwiazany do konca :(
W tym momencie chcialbym serdecznie podziekowac tym ktorzy tracili swoj cenny czas na pomaganie mi (pisanie algo, tlumaczenie c do delphi itd).
Algo nie dziala w momencie pustych stringow ('')
np.

edit1. Alaa
edit2. ala*a

Pokazuje ze sa nie rowne. A ja chcialbym zeby byly rowne. Czyli gwiazdka moze byc tez pusta.

Ktos ma jakis pomysl na przeksztaucenie tego?
Pozdrawiam,
Mupet

Ps. Delphi znam dosc dobrze jesli chodzi o skladnie, funkcje itd. Pisze w nim od kilku lat. po prostu nie mialem zadnego pomyslu na ten algo (moze brak inteligencji?) - na pewno predzej niz brak znajomosci Delphiego. Zato c++ nie znam w ogole - przyznaje sie bez bicia.

0

A nie jest to czasem problem różnicy wielkości litery? tzn ten przykład co podałeś przed chwilą?

0

A nie jest to czasem problem różnicy wielkości litery? tzn ten przykład co podałeś przed chwilą?

nieszkodzi, przy alaa i ala*a tez nie dziala. gadalismy na GG.

//DOPISANE

zmienilem juz kod wyzej zgodnie z instrukcja foflika ponizej. Jak cos nie dziala to jego wina :)

0

Nie chce mi sie za bardzo sprawdzac, ale wydaje mi sie, ze dla mojego kodu powinna pomoc zamiana

if (!znalazl)
        return false;

na

if (!znalazl)
        return czy_rowne(S1 + i, S2 + i + 1);

Ale jak mowie, nie wiem, czy to nie wprowadzi bledow. I jeszcze taka uwaga dla "tlumacza" . Wydaje mi sie, ze lepiej by bylo uzyc, jako typy argumentow PChar niz String, bo to to samo (tak mi sie wydaje) co char * w C.</cpp>

0

No niestety Twoja przerobka kodu foflik nie dziala :(

s1="ala32423"
s2="alamakota"

Wyskakuje "stack overlow", albo to :

s1="ala324823ma3423kot"
s2="alamakota"

Wynik funkcji jest true, czyli ze sie zgadzaja. Mimo ze oczywiste jest ze tak nie powinno byc (kot,kota).

Pozdrawiam,
Mupet

1 użytkowników online, w tym zalogowanych: 0, gości: 1