Słownik(drzewo binarne) - pascal

0

Witam.
Zgłaszam się do was o poradę po raz drugi, a za poprzednią bardzo dziękuję!

Mam do napisania tłumacz polsko-angielski, angielsko-polski. Plik słownika może być dowolnej długości i ma być w formie:

kot cat
pies dog
ryba fish

Mam wykorzystać do tego drzewo binarne. Dla jezyka polskiego zbudowane jest w ten sposób, ze wyrazy, które stoją wcześniej w porządku alfabetycznym są po lewej stronie wezła, a te, które stoja pózniej – po prawej stronie. Te same elementy, które
naleza do drzewa dla jezyka polskiego, sa takze elementami drzewa dla jezyka angielskiego zbudowanego według porzadku alfabetycznego wyrazów angielskich.
No i tu mam pierwszą wątpliwość. Koncept drzewa binarnego rozumiem jednak zastanawiam się jak porównać wyrazy alfabetycznie, żeby odpowiednio wstawić je do drzewa i czy w korzeniu ma być wyraz, który jest w 'alfabetycznym środku'? I patrząc na kolejne węzły: w prawym węźle ma być słowo, które jest następne alfabetycznie(czy po prostu, takie, które jest dalej w alfabecie, ale niekoniecznie następne?) a w lewym poprzednie(czy niekoniecznie?)? Jeżeli muszą być po kolei, czyli, że najbardziej w prawym dole jest ostatnie alfabetycznie słowo a najbardziej w lewym dole jest słowo pierwsze, to jak porównać te słowa i je odpowiednie ułożyć?

Generalnie trochę zagmatwałem pewnie więc TL/DR: Jak ułożyć wyrazy w porządku alfabetycznym i jak wprowadzić je do drzewa?

I jeszcze jedno pytanie niezwiązane z samym tłumaczem, ale nigdy czegoś takiego nie robiłem i byłbym wdzięczny za wskazówkę jak to zrobić?:
Program uruchamiany jest z linii polecen z wykorzystaniem następujących przełączników:
-s plik wejsciowy słownika
-i plik wejsciowy z tekstem do przetłumaczenia
-o plik wyjsciowy z przetłumaczonym tekstem
-k kierunek tłumaczenia

Z góry dziękuję za pomoc.

EDIT: Już wiem, że to co napisałem z drzewem binarnym jest bez sensu, po prawej nie musi być następne słowo a po lewej nie musi być po przednie, tak jest tylko w przypadku gdy lewy/prawy węzeł nie ma już dalszych synów, rozumiem. Pytanie jednak dalej zostaje, jak wprowadzać te słowa do drzewa?

EDIT2: Oh my! Rozumiem, przy dodawaniu każdego słowa, zaczynam od korzenia, czyli nie ma opcji, że jakimś cudem po prawej stronie znajdzie się coś większego od korzenia. Mój błąd, źle zrozumiałem drzewo binarne. Jak porównać jednak, które słowo jest dalej w alfabecie, a które bliżej? Z tą wiedzą spróbuję sobie z tym teraz poradzić. Z góry dzięki!

0

To z czym masz problem?

0

Przełączniki! Prosiłbym o pomoc z przełącznikami : ). Dzięki z góry.

1
for I:=1 to ParamCount() do
begin
  WriteLn(ParamStr(I));
end;
0

A jakiś mądry sposób na wczytanie do stringa pierwszego słowa w linii? Bo drugiego (angielskiego) nie ma problemu, po prostu readln po spacji, a tutaj? Trzeba wszystko do spacji wczytać z tym, że nie wiem jak. Jak traktuje mojego stringa jak tablicę charów to wywala mi błąd przy pracy programu.

0

Albo ręcznie przewertuj w pętli łańcuch w poszukiwaniu białego znaku, albo skorzystaj z ExtractStrings, albo połącz Copy/LeftStr z Pos - to jeśli chodzi o wyciągnięcie części ciągu do pierwszej spacji;

Jeśli chcesz sprawdzać po każdorazowym wciśnięciu klawisza czy to spacja to skorzystaj z pętli i wprowadzaj znak po znaku, a nie całą linię (bo zakończysz ją dopiero wciskając Enter); Proponowałbym wczytać całą linię, po jej zatwierdzeniu klawiszem Enter sprawdzić jej zawartość i odpowiednio zareagować;

0

No właśnie tak zrobiłem. Wczytałem całą linie i teraz chciałbym ją podzielić na 2 wyrazy (w każdej linii są 2 wyrazy) i nie umiem sobie poradzić z tym ExtractStrings, potrzebuje dziwnych typów zmiennych.

Mam linie wczytaną do zmiennej linia, co muszę zadeklarować i w pisać pod 'Foo' i 'Memo1.Lines'?

ExtractStrings([',', ';'], [], Foo, Memo1.Lines);

EDIT: ok, zrobiłem z leftstr i rightstr. Dzięki wielkie za pomoc : ). Code on.

0

To skorzystaj z Pos i Copy.

0

Wczytałem całą linie i teraz chciałbym ją podzielić na 2 wyrazy (w każdej linii są 2 wyrazy)

Jeśli chcesz użyć ExtractStrings to musisz mieć osobną zmienną - nie możesz wykorzystać do tego celu pola TMemo.Lines pomimo tego, że sa tego samego typu;

0

tak właśnie zrobiłem, obędzie się bez extractstrings. Dzięki wielkie za pomoc! Code on.

0

Nie wiem niestety czy nie będę potrzebował jednak ExtractStrings, albo jakiejś innej metody, przy czytaniu pliku z tekstem źródłowym. Muszę jakoś rozdzielić zwykły tekst(który chyba muszę w całości wrzucić do stringa?) na wyrazy, żeby móc je wyszukiwać w drzewie. Coś innego niż ExtractStrings znajdę? : >

0

Sorry, ale jesteś jakiś ograniczony? Dostałeś odpowiedź:

olesio napisał(a):

To skorzystaj z Pos i Copy.

0

Tutaj akurat ExtractStrings nie zaszkodzi, choć jak wiadomo - można to rozwiązać na wiele sposobów, najważniejsze, żeby najpierw spróbować jakiegokolwiek sposobu, potem ewentualnie pytać;

0

@GooglujZanimZapytasz
Poprzedni problem rozwiązałem Pos i Copy, nie unoś się. Pytam o ExtractStrings bo Pos wskazuje miejsce pierwszego wystąpienia np. spacji w tekście, więc mając cały tekst i wiele spacji optymalnie byłoby to zrobić czymś takim jak właśnie ExtrackStrings. Ew użyję PosEx'a o którym właśnie teraz doczytałem, więc odpowiedź 'użyj Pos i Copy' dla newbie(bo w tej części forum jesteśmy) nie koniecznie wszystko wyjaśnia. Dzieki za pomoć @FP anywayz. Dobranoc

1

Pytam o ExtractStrings bo Pos wskazuje miejsce pierwszego wystąpienia np. spacji w tekście, więc mając cały tekst i wiele spacji optymalnie byłoby to zrobić czymś takim jak właśnie ExtrackStrings.

Jeśli chcesz używać dodatkowych obiektów to najszybciej i najwygodniej jest podzielić łańcuch znaków właśnie dzięki tej procedurze; Po podzieleniu elegancko w pętli można sprawdzać poszczególne słowo w liście, bez zbędnego kopiowania, szukania itd.; Także nie powinno się nic złego stać, jeśli wczytasz pustą linię - po prostu lista będzie pusta i sprawdzając przed pętlą ilość uzyskanych wyrazów odpowiednio odrzucisz sprawdzanie;

Ew użyję PosEx'a o którym właśnie teraz doczytałem, więc odpowiedź 'użyj Pos i Copy' dla newbie(bo w tej części forum jesteśmy) nie koniecznie wszystko wyjaśnia.

Możesz także wykorzystać Copy, Pos i PosEx do ręcznego wyszukiwania słów, ale z tym będzie więcej roboty i debuger przyda się w razie kłopotów; Żeby wykorzystać Pos, PosEx i Copy sugerowałbym dodatkowo stworzyć znacznik, który wskazywać będzie na początek aktualnego słowa w ciągu i znacznik wskazujący na indeks znaku po przeszukaniu przez Pos/PosEx, coś mniej więcej na ten kształt:

uses
  StrUtils;
const
  chrSep = Char(#32);
var
  sLine: String = 'To jest ciag do przeszukania i podzielenia na wyrazy';
  wWordChrIdx, wSepIdx: Word;
begin
  if Length(sLine) > 0 then
  begin
    wWordChrIdx := 1;

    repeat
      wSepIdx := PosEx(chrSep, sLine, wWordChrIdx);

      if wSepIdx = 0 then
        WriteLn('"', Copy(sLine, wWordChrIdx, Length(sLine) - Pred(wWordChrIdx)), '"')
      else
      begin
        WriteLn('"', Copy(sLine, wWordChrIdx, wSepIdx - wWordChrIdx), '"');
        wWordChrIdx := Succ(wSepIdx);
      end;
    until wSepIdx = 0;
  end;

  ReadLn;
end.

no i w ten sposób można bardzo łatwo podzielić łańcuch na wyrazy, z tym, że jeśli w łańcuchu znajdują się nieporządane znaki jak [',', '.', ';', ':', '!', '?'] itd. to będzie trzeba odpowiednio je pomijać/usuwać; Ww. kod jest tak skonstruowany, by wykorzystać tylko Copy i PosEx - zwykły Pos nie jest potrzebny; Przeanalizuj sobie (nawet pod debugerem) i sprawdź jak to działa;

'użyj Pos i Copy' dla newbie(bo w tej części forum jesteśmy) nie koniecznie wszystko wyjaśnia.

Nie możesz liczyć na to, że będziemy Cię uczyć programować - tutaj możesz uzyskać pomoc jeśli chodzi o niedziałający kod, a nie o brak wiedzy; Dostałeś wskazówkę na temat przydatnych funkcji, więc trzeba przejść choćby do działu Delphi i poczytać do czego służą te funkcje i jak z nich korzystać; Już i tak podałem Ci kawałek kodu, więc przeanalizuj go sobie i naucz się wykorzystywać wspomniane funkcje/procedury, a także zanim zapytasz o coś najpierw poszukaj o tym w sieci i pomocy (szczególnie w pomocy środowiska - tam jest wszystko objaśnione);

0

Ok, napisałem cały program(tak mi się przynajmniej wydaje). Nie wiem czy chciałoby się wam czytać cały mój kod (chętnie go wrzucę tho) w każdym razie proszę o pomoc w znalezieniu błędu. Wrzucam tylko to z czym jest problem i to z czym jest to powiązane(czytać od dołu) :

procedure NoweDrzewo(var wezel:wsk_Drzewo);
     begin
     new(wezel);
     wezel^.LewyWezel:=nil;
     wezel^.PrawyWezel:=nil;
     wezel^.klucz:='';
     wezel^.tlumaczenie:='';
     end;


function BudowanieDrzewa(wezelek:wsk_Drzewo; slowo_klucz, tlumaczenie: string): wsk_Drzewo;
var
  pomocniczy:wsk_Drzewo;

begin
  if (slowo_klucz < wezelek^.klucz) then
  begin
    if wezelek^.LewyWezel=nil then
    begin
      NoweDrzewo(pomocniczy);
      pomocniczy^.klucz:=slowo_klucz;
      pomocniczy^.tlumaczenie:=tlumaczenie;
      wezelek^.LewyWezel:=pomocniczy;
    end
    else
      BudowanieDrzewa(wezelek^.LewyWezel, slowo_klucz, tlumaczenie)
  end
  else if (slowo_klucz >= wezelek^.klucz) then
  begin
    if wezelek^.PrawyWezel=nil then
    begin
      NoweDrzewo(pomocniczy);
      pomocniczy^.klucz:=slowo_klucz;
      pomocniczy^.tlumaczenie:=tlumaczenie;
      wezelek^.PrawyWezel:=pomocniczy;
    end
    else
      BudowanieDrzewa(wezelek^.PrawyWezel, slowo_klucz, tlumaczenie)
  end;
  BudowanieDrzewa:=wezelek;
end;

function CzytanieSlownika(wejscie_slownika, kierunek_tlumaczenia: string): wsk_Drzewo;
var
  wezel:wsk_Drzewo;
  slownik: Text;
  slowo_klucz, tlumaczenie, linia: string;
  i, j: integer;

begin
  Assign(slownik, wejscie_slownika);
  reset(slownik);
  NoweDrzewo(wezel);
  if kierunek_tlumaczenia=angielski_na_polski then
    begin
      repeat
        readln(slownik, linia);
        i:=Pos(' ', linia);
        tlumaczenie:=Copy(linia, 1, i-1);
        j:=length(linia)-i;
        slowo_klucz:=Copy(linia, i+1, j);
        wezel:=BudowanieDrzewa(wezel, slowo_klucz, tlumaczenie);
      until EOF(slownik);
    end
  else if kierunek_tlumaczenia=polski_na_angielski then
    begin
      repeat
        readln(slownik, linia);
        i:=Pos(' ', linia);
        slowo_klucz:=Copy(linia, 1, i-1);
        j:=length(linia)-i;
        tlumaczenie:=Copy(linia, i+1, j);
        wezel:=BudowanieDrzewa(wezel, slowo_klucz, tlumaczenie);
      until EOF(slownik);
    end;
  close(slownik);
  CzytanieSlownika:=wezel;
end;

function TlumaczenieSlowa(wezel: wsk_Drzewo; wyraz: string): string;
begin
  if wezel=nil then TlumaczenieSlowa:=wyraz;
  if wezel^.klucz=wyraz then TlumaczenieSlowa:=wezel^.tlumaczenie
  else if wyraz < wezel^.klucz then TlumaczenieSlowa:=TlumaczenieSlowa(wezel^.LewyWezel, wyraz)
  else if wyraz > wezel^.klucz then TlumaczenieSlowa:=TlumaczenieSlowa(wezel^.PrawyWezel, wyraz)
end;


function TlumaczenieTekstu(wezel: wsk_Drzewo; tekst_do_tlumaczenia: string): string;
var
  PoczatekWyrazu, PozycjaSpacji: integer;
  zrodlo: text;
  tekst_zrodlowy, wyraz, przetlumaczony_wyraz: string;

begin
  Assign(zrodlo, tekst_do_tlumaczenia);
  reset(zrodlo);
  read(zrodlo, tekst_zrodlowy);
  close(zrodlo);
  PoczatekWyrazu := 1;
  repeat
    PozycjaSpacji := PosEx(spacja, tekst_zrodlowy, PoczatekWyrazu);
    if PozycjaSpacji = 0 then
    begin
      wyraz:=Copy(tekst_zrodlowy, PoczatekWyrazu, Length(tekst_zrodlowy) - Pred(PoczatekWyrazu));
    end
    else
    begin
      wyraz:=Copy(tekst_zrodlowy, PoczatekWyrazu, PozycjaSpacji - PoczatekWyrazu);
      PoczatekWyrazu := Succ(PozycjaSpacji);
    end;
    przetlumaczony_wyraz:=TlumaczenieSlowa(wezel, wyraz);
    tekst_zrodlowy:=StringReplace(tekst_zrodlowy, wyraz, przetlumaczony_wyraz, []);
  until PozycjaSpacji = 0;
  TlumaczenieTekstu:=tekst_zrodlowy;
end;

{główna pętla programu: }
Begin

  korzen:=CzytanieSlownika(wejscie_slownika, kierunek_tlumaczenia);
  przetlumaczony_tekst:=TlumaczenieTekstu(korzen, tekst_do_tlumaczenia);

end.

Błąd Project raised exception class 'External SIGSEGV' wyskakuje w funkcji TłumaczenieSłowa (w linijce:

if wezel^.klucz=wyraz then TlumaczenieSlowa:=wezel^.tlumaczenie

). Pojawił mi się już wcześniej i był związany z jakimś błędem w kodzie np. odwoływaniem się do nieistniejących komórek pamięci, albo do pliku tekstowego, którego nie ma. Tym razem nie umiem sobię jednak poradzić.

Po krótce co robię: do zmiennej korzen przypisuję Drzewo binarne ze słownikiem. do zmiennej przetlumaczony_tekst przypisuję string z tekstem po wyszukaniu i zamianie każdego słowa z tekstu źródłowego znalezionego w tym drzewie binarnym. Problem tkwi zapewne we wskaźnikach, nie jestem pewny czy dobrze to zrobiłem. Z góry wieeeeelkie dzięki za pomoc.

1

W funkcji BudowanieDrzewa nie widzę obsługi dodawania pierwszego słowa.

Zamięń procedure NoweDrzewo ... na:

function NoweDrzewo(const klucz,tlumaczenie:String);
begin
     new(NoweDrzewo);
     NoweDrzewo^.LewyWezel:=nil;
     NoweDrzewo^.PrawyWezel:=nil;
     NoweDrzewo^.klucz:=klucz;
     NoweDrzewo^.tlumaczenie:=tlumaczenie;
end;

wtedy w BudowanieDrzewa:

    if wezelek^.LewyWezel=nil then wezelek^.LewyWezel:=NoweDrzewo(slowo_klucz,tlumaczenie)
    else ...
0

Po zmianie tego co mówisz nie kompiluje: "tlumacz.pas(45,6) Error: Wrong number of parameters specified for call to "NoweDrzewo"
". w każdym miejscu gdzie jest NoweDrzewo. btw. w funkcji Czytanie Slownika też się odwołuję do NoweDrzewo.

EDIT: sorry mój błąd, nie zmieniłem procedury na funkcje... Odezwę się, dzięki wielkie ze pomoc w każdym razie!

EDIT2: Ale dalej (za ok. godziny będę na stacjonarce więc będę miał kompilator, wtedy pokombinuję) co zrobić z linią w funkcji CzytanieSlownika?:

NoweDrzewo(wezel);
0

Aaa co do obsługi budowania pierwszego słowa, to nie jest to właśnie w funkcji CzytanieSlownika, gdzie robimy korzeń drzewa? Linjka:

NoweDrzewo(wezel);

Po sugerowanych zmianach problem został ten sam. Proszę o dalsze wskazówki jeśli to możliwe, wielkie dzięki.

EDIT: i jeszcze głupie pytanie, te funkcje robią dokładnie to samo i są poprawne? (bo nie wiedziałem właściwie, że mogę zrobić to tak jak w drugiej funkcji. Teraz wiem!):

function NoweDrzewo(klucz, tlumaczenie: String): wsk_Drzewo;
var
  NoweDrzewo1: wsk_Drzewo;
   begin
     new(NoweDrzewo1);
     NoweDrzewo1^.LewyWezel:=nil;
     NoweDrzewo1^.PrawyWezel:=nil;
     NoweDrzewo1^.klucz:=klucz;
     NoweDrzewo1^.tlumaczenie:=tlumaczenie;
     NoweDrzewo:=NoweDrzewo1;
   end;   
function NoweDrzewo(klucz, tlumaczenie: String): wsk_Drzewo;
   begin
     new(NoweDrzewo);
     NoweDrzewo^.LewyWezel:=nil;
     NoweDrzewo^.PrawyWezel:=nil;
     NoweDrzewo^.klucz:=klucz;
     NoweDrzewo^.tlumaczenie:=tlumaczenie;
   end;       
0

Problem zostaje ten sam: "W funkcji BudowanieDrzewa nie widzę obsługi dodawania pierwszego słowa."
Ma być tam, koniec kropka. Nie możesz tak po prostu byle co wsadzić jako korzeń. Stąd wynikają pozostałe problemy.

0

Więc jako korzeń mam wstawić pierwsze słowo słownika? To może zrobię to w CzytanieSlownika, zanim zacznie się pętla repeat?

1
function CzytanieSlownika(wejscie_slownika, kierunek_tlumaczenia: string): wsk_Drzewo;
var wezel:wsk_Drzewo;
 ... 
begin
 ... 
       wezel:=nil;
 ... 
        BudowanieDrzewa(wezel, slowo_klucz, tlumaczenie);
 ... 
        BudowanieDrzewa(wezel, slowo_klucz, tlumaczenie);
 ... 
  CzytanieSlownika:=wezel;
end;

procedure BudowanieDrzewa(var wezelek:wsk_Drzewo; slowo_klucz, tlumaczenie: string);
begin
  if wezelek=nil then wezelek:=Drzewo(slowo_klucz,tlumaczenie)
  else if (slowo_klucz < wezelek^.klucz) then BudowanieDrzewa(wezelek^.LewyWezel, slowo_klucz, tlumaczenie)
  else if (slowo_klucz > wezelek^.klucz) then BudowanieDrzewa(wezelek^.PrawyWezel, slowo_klucz, tlumaczenie);
end;
0

Nie bardzo rozumiem kiedy właściwie mam robić procedurę a kiedy funkcję? Bo przed chwilą zmieniając jedną procedurę na funkcje słownik zaczął jako tako tłumaczyć, chociaż nie robi tego do końca dobrze. Wydawało mi się, że BudowanieDrzewa powinno zwracać to drzewo a okazuje się, ze jednak nie? Czyli samo wykonanie procedury na węźle w funkcji CzytanieSlownika zmienia ten wezel?

EDIT: OOOOk rozumiem - var w nawiasie pozwala nam na modyfikowanie parametrów, przepraszam, nie wiedziałem! Dzięki wielkie za pomoc!

EDIT: ok działa, jeszcze raz wielkie dzięki za pomoc! : ) Nie zmienia to faktu, że jeszcze jedną rzecz do poprawienia mam. Jest może funkcja, podobna do StringReplace, ale która nie zmienia pierwszego napotkanego wystąpienia klucza ale np. od pewnego momentu? Na chwilę obecną właśnie StringReplace'm to tłumaczę ale nie jest to optymalne i przy krótkich słowach typu "i", "no" spotyka je w środku większych wyrazów i tłumaczy.

1

nie tędy droga.
Zastanów się jak ci przetłumaczy tekst "witaj kochanie"
kochanie zamieni na baby
po czym baby zamieni na "old wemen"
więc w sumie wyjdzie "hello old wemen".
Masz podzielić tekst na osobne słowa, zaś później każde przetłumaczyć lub zostawić jak jest.
I znowu skleić.

1

Na chwilę obecną właśnie StringReplace'm to tłumaczę ale nie jest to optymalne i przy krótkich słowach typu "i", "no" spotyka je w środku większych wyrazów i tłumaczy.

Jeśli potrzebujesz zamienić "tylko całe wyrazy" tak, jak możliwe jest wyszukiwanie tekstu dzięki Whole words only w edytorach tekstowych (do tego nawet jest cały dialog - TFindDialog) to musisz albo ręcznie przeszukiwać ciąg, albo podzielić go na wyrazy (tutaj znowu nadchodzi z pomocą ExtractStrings lub opisana przeze mnie wcześniej metoda z Copy i PosEx) i dopiero wtedy w pętli pozamieniać (StringReplace wtedy już niepotrzebne) i skleić gotowy ciąg do kupy; Dzięki metodzie PosEx możesz to wykonać szybciej bez zbędnego rozdzielania łańcucha i łączenia go z powrotem - jest szansa zaoszczędzić czas, choć pewności nabrałbym po testach;

Tak na szybko napisałem prosty algorytm wyszukujący dany wyraz (odrzucający część innego wyrazu) i zamieniający go na inny; Wykorzystałem PosEx, Delete i Insert tak, by bezpośrednio operować na całym łańcuchu wejściowym; Algorytm odrzuca szukane słowo znalezione wewnątrz innego słowa, a także rozróżnia wielkość liter, dlatego że funkcja PosEx je rozróżnia:

uses
  StrUtils;
const
  chrSep = Char(#32);
  sSearchWord = AnsiString('to');
  sReplaceThe = AnsiString('tamto');
  iSearchWordLen = Length(sSearchWord);
var
  sLine: AnsiString = 'To jest lotto a To lotto wie to ze to To nie tom';
  wCurrChrIdx: Word = 0;
  wEndWordChrIdx: Word;
begin
  WriteLn('Before: "', sLine, '"');
  wCurrChrIdx := PosEx(sSearchWord, sLine, wCurrChrIdx);

  while wCurrChrIdx <> 0 do
  begin
    if (wCurrChrIdx > 1) and (sLine[Pred(wCurrChrIdx)] <> chrSep) then
      Inc(wCurrChrIdx, iSearchWordLen)
    else
      if (wCurrChrIdx + Pred(iSearchWordLen) < Length(sLine)) and
         (sLine[wCurrChrIdx + iSearchWordLen] <> chrSep) then
        Inc(wCurrChrIdx, iSearchWordLen)
      else
      begin
        wEndWordChrIdx := PosEx(chrSep, sLine, wCurrChrIdx);

        if wEndWordChrIdx = 0 then
          wEndWordChrIdx := Succ(Length(sLine));

        Delete(sLine, wCurrChrIdx, wEndWordChrIdx - wCurrChrIdx);
        Insert(sReplaceThe, sLine, wCurrChrIdx);
        Inc(wCurrChrIdx, Succ(Length(sReplaceThe)));
      end;
 
    wCurrChrIdx := PosEx(sSearchWord, sLine, wCurrChrIdx);
  end;
 
  Write('After:  "', sLine, '"');
  ReadLn;
end.

i tak na wyjściu zobaczymy:

Before: "To jest lotto a To lotto wie to ze to To nie tom"
After:  "To jest lotto a To lotto wie tamto ze tamto To nie tom"

Sprawdź najlepiej pod debugerem jak to działa - zasada jest bardzo prosta;

Jeśli chciałbyś aby algorytm nie rozróżniał wielkości liter - najprawdopodobniej zamiast wyszukiwać danego słowa funkcją PosEx trzeba by ręcznie sprawdzać każdy znak ciągu wejściowego i np. funkcją SameText lub CompareText sprawdzać czy aktualny znak ciągu jest literą taką samą jak pierwszy znak szukanego słowa, następnie sprawdzić czy pod tym indeksem w ciągu wejściowym znajduje się szukane słowo, a następnie sprawdzić, czy jest to całe słowo, czy znalezione wewnątrz innego słowa i dopiero jeśli wszystko się zgadza - dokonać zamiany; Jednak myślę, że Tobie raczej chodzi o rozróżnianie wielkości liter, więc powyższy algorytm powinien być dobry;

EDIT: Naprawiłem jeszcze jeden błąd - jeśli ostatnie słowo (tak jak w przykładzie wyżej) zaczynało się szukanym słowem, ale było tylko częścią innego - nie zostanie zamieniony;

0

Dzięki wam bardzo! Użyłem funkcji Insert zapisując każde tłumaczone słowo do nowego stringa Przetlumaczony_tekst, dzięki temu zmieniam dokładnie te wyrazy które chce.
Obiecuję, że już ostatnie pytania w tym temacie (chociaż pisząc to sam próbuję do tego dojść więc dam znać jakby mi się udało) - do dzielenia tekstu na wyrazy używam posex i copy, jak sobie poradzić ze znakami interpunkcyjnymi, które mają po prostu zostać niezmienione?

2

Niepoprawnie dzielisz.

{$mode objfpc}
uses Classes;

function translate(const word:String):String;
begin
  if word='kot' then Result:='cat'
  else if word='kota' then Result:='cat'
  else if word='zaś' then Result:='but'
  else if word='ma' then Result:='got'
  else if word='gdzieś' then Result:='somewhere'
  else Result:=word;
end;

function IsAlpha(Ch:Char):Boolean;
begin
  Result:=(Pos(Ch,'aąbcćdeęfghijklłmnńoópqrsśtuvwxyzżźAĄBCĆ')>0); // sam wpiszesz resztę
end;

var itext,otext,word,sign:String;
var Si,So:TStringStream;
begin
  itext:='Ala, ma kota, zaś kot - ma Ale gdzieś!';
  So:=TStringStream.Create('');
  try
    Si:=TStringStream.Create(itext);
    try
      SetLength(word,0);
      SetLength(sign,0);
      while true do
      begin
        sign:=Si.ReadString(1);
        if (Length(sign)>0)and(IsAlpha(sign[1])) then
        begin
          word:=word+sign;
        end
        else
        begin
          if Length(word)>0 then word:=translate(word);
          So.WriteString(word+sign);
          SetLength(word,0);
        end;
        if Length(sign)<=0 then Break;
      end;
    finally
      Si.Free;
    end;
    otext:=So.DataString;
  finally
    So.Free;
  end;
  WriteLn(otext);
  ReadLn;
end.
0

Dzięki bardzo!

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