Program do koniungacji czasowników włoskich

0

Zachęcony do programowania obiektowego, zacząłem trochę dłubać i powolutku próbuje zrozumieć o co w tym wszystkim chodzi. Oczywiście wciąż mam duże problemy dlatego proszę o dozę wyrozumiałości w tłumaczeniu pewnym aspektów ;)

Postanowiłem ostatnio pobawić się trochę w Lazarusie, a jako, że studiuję filologię i pasjonuję się językami to postanowiłem zrobić prosty program, w którym mógłbym wpisać czasownik, a program sam by to słowo odmienił.
Tak wyglada program

a tutaj kod. I mam takie pytanie
Jak dodawać wyjątki od reguł? Tworzyć nowe funkcje czy tak jak teraz to robiłem czyli jedna pod drugą? Wydaje mi się to mocno ślamazarne, ale nie bardzo miałem pomysł jak to ogarnąć może poza jakimś if'em.

Z góry dziękuję za pomoc :)

/ Edit: zaznaczam, że w kodzie mogą pojawiać się zmienne nieużyte w programie. To efekt tego, że kombinuję ciągle i bawię się na różne sposoby jak to zrobić :)

unit unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, StrUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TMainForm }

  TMainForm = class(TForm)
    btnOK: TButton;
    lblFirstSingularPresentIndicative: TLabel;
    lblSecondSingularPresentIndicative: TLabel;
    lblThirdSingularPresentIndicative: TLabel;
    lblFirstPluralPresentIndicative: TLabel;
    lblSecondPluralPresentIndicative: TLabel;
    lblThirdPluralPresentIndicative: TLabel;
    VerbEdit: TEdit;
    PersonBox: TGroupBox;
    lblFirstSingular: TLabel;
    lblSecondSingular: TLabel;
    lblThirdSingular: TLabel;
    lblFirstPlural: TLabel;
    lblSecondPlural: TLabel;
    lblThirdPlural: TLabel;
    procedure btnOKClick(Sender: TObject);
    procedure PersonBoxClick(Sender: TObject);
    procedure VerbEditChange(Sender: TObject);
  private

  public

  end;

var
  MainForm: TMainForm;
  StringLenght: Integer;
  Verb: String;
	k: String;
  L: Integer;
  X : Boolean;

implementation

{$R *.lfm}

{ TMainForm }

procedure TMainForm.VerbEditChange(Sender: TObject);
begin
  Verb := Trim(LowerCase(VerbEdit.Text));
  L := Length(Verb);
end;

procedure TMainForm.btnOKClick(Sender: TObject);
begin
  X := AnsiEndsStr('are', Verb);
  if X = true then
  begin
    Delete(Verb, L-2, 3);
    lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + 'o');
  	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + 'i');
    lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'a');
    lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + 'iamo');
    lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ate');
    lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ano');
  end;
  X := AnsiEndsStr('ere', Verb);
  if X = true then
  begin
  	Delete(Verb, L-2, 3);
    lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + 'o');
  	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + 'i');
    lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'a');
    lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + 'iamo');
    lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ete');
    lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ono');
  end;

  X := AnsiEndsStr('ire', Verb);
  if X = true then
  begin
    Delete(Verb, L-2, 3);
    lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + 'o');
  	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + 'i');
    lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'e');
    lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + 'iamo');
    lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ite');
    lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ono');
  end;
end;

procedure TMainForm.PersonBoxClick(Sender: TObject);
begin

end;

end.


4

Ciężko coś powiedzieć, bo nie znam za bardzo reguł włoskiej deklinacji, ale zakładając, że większość czasowników jest regularna/odmienia się zgodnie z jakimś schematem/zasadami, to bym zrobił następująco:

1) stworzyć listę czasowników nieregularnych, do których trzeba będzie ręcznie wpisać ich poszczególne formy. To aż się prosi o umieszczenie w jakiejś tablicy
**2) **po otrzymaniu od użytkownika wyrazu, który chcesz odmienić (czy co tam konkretnie chcesz z nim robić) sprawdzasz w tablicy z pkt. 1, czy ten wyraz się w nim znajduje. Jeśli jest, to wypisujesz to, co jest do niego przypisane w tablicy
3) jeśli jednak danego wyrazu nie ma w tablicy, to znaczy, że się powinien odmieniać regularnie, w związku z czym przepuszczasz go przez algorytm, który dopisuje odpowiednie końcówki (lub robi cokolwiek innego).
4) nie wiem, na ile to dla Ciebie jest zabawa/ćwiczenie, a na ile ten program ma się do czegoś przydać. Jeśli ma być wykorzystywany, to chyba koniecznością jest jakieś zapisywanie wprowadzonych wcześniej wyników do bazy, żeby potem można było je załadować. W związku z tym proponuję się zainteresować SQLite - niby baza SQL, ale mega prosta w obsłudze.

To, co napisałeś - może i działa, ale moim zdaniem nadaje się do poprawki. Zobacz - praktycznie większość kodu to jest powtarzanie tego samego. Dla trzech wariantów (ORE, ARE, IRE) masz praktycznie do samo, takie kopiuj-wklej. Zastanów się, jakie operacje tam wykonujesz i wyodrębnij je do osobnej funkcji, która będzie wywoływana z odpowiednim parametrem.

0

Hej, dzięki za odpowiedź!
Wiesz co. Na razie bawię się. Jako, że uczę się włoskiego to fajnie byłoby go używać tylko do sprawdzenia formy, oczywiście jakby się udało to może kiedyś go rozbuduję do większej ilości czasów, trybów itd. W tej chwili mam czas teraźniejszy z końcówkami -are, -ere i -ire i działa. Oczywiście nie uwzględnia b. wielu czynników, z którymi będzie problem jak np. akcent wyrazowy, ale o tym pomyślę później. Pomysł z bazą nie jest głupi i z pewnością o tym pomyślę, tyle, że obecnie ja dopiero próbuję zrozumieć programowanie obiektowe więc chcę małymi krokami :)

Obecnie zrobiłem tak, że funkcja AnsiEndsStr sprawdza zmienna Verb posiada na końcu jeden z trzech ciągów (mianowicie -are, -ere i -ire) i jeżeli tak to uruchamia if'a który dodaje odpowiednie końcówki.

Co myślisz o takim pomyśle by część czasowników nieregularnych czytał z pliku jakiegoś? Tzn. w pliku znajdowałaby się lista czasowników i jeżeli by znalazł to wykonywał by konkretną funkcję. Tyle, że zdaje sobie sprawę, że przy pewnych czasownikach to może nie zdać egzaminu, ale co sądzisz samym pomyśle?

1

Po pierwsze - nie chcę zniszczyć Twojego światopoglądu, ale to co napisałeś nie ma za wiele wspólnego z projektowaniem obiektowym. Owszem, TForm1 jest obiektem posiadającym elementy - przyciski, edity itp, ale na tym obiektowość się kończy :P

Co do bazy - wbrew pozorom. SQL (a zwłaszcza SQLIte) to prosty temat. Oczywiście - stworzenie skomplikowanych aplikacji z tysiącami użytkowników i bazami rosnącymi w TB to zupełnie inna liga, ale zrobienie prostej bazy, do której się zapisze/z której się odczyta listę słówek to zadanie proste. W mojej ocenie nawet prostsze, niż samodzielne walczenie z jakimś plikiem trzymającym listę słów, jego odczytywaniem, zapisywaniem, modyfikacjami itp. W przypadku SQL zasadniczo wszystko się ogranicza do wydania jednego polecenia - INSERT dopisuje dane, UPDATE poprawia itp.

A co do wykrywania słów i ich automatycznego przerabiania - jak pisałem wcześniej, totalnie nie znam tego języka, więc może nie mam racji, ale moim zdaniem możliwa jest taka sytuacja, w której danego słowa nie ma na liście wyjątków, więc program potraktuje je jako przypadek regularnej odmiany, w związku z czym wypisze jakieś głupoty. Czy jest taka możliwość?

0

Jasne, że jest. Jak każdy język, włoski rządzi się swoimi prawami i taki przypadek pewnie by się znalazł chociaż tak na szybko nic nie przychodzi mi do głowy :)
Co do programowania obiektowego to nie obrażam się ani nic, bo tak jak mówiłem, nie zawsze wiem jak go użyć i kiedy. Tutaj bawiłem się w formach więc założyłem, że to raczej już obiektowość. Nie bardzo mam pomysł jak zrobić to w jakiejś klasie czy coś dlatego na razie tak karkołomnie to wygląda. :)

Co do tej bazy to skoro mówisz, że tak to wygląda to może faktycznie spróbuje sił w tym :)

2

Zasadniczo fakt, że w kodzie się skorzysta z obiektów nie czyni od razu kodu obiektowym. Tak samo, jak Polonez na torze rajdowym nagle nie stanie się wyścigówką ;)
Aczkolwiek rozumiem, że się uczysz, więc ze spokojem, wszystko w swoim czasie. I żeby nie było niedomówień - nie krytykowałem Cię ani tego co napisałeś, tylko chciałem, żebyś miał świadomość, że to nie jest OOP.

Na razie, zamiast skupiać się na obiektowości, na Twoim miejscu zająłbym się raczej uzyskaniem takiej ogólnej biegłości w Pascalu. Pierwszym zadaniem które powinieneś wykonać (o którym zresztą pisałem we wcześniejszych postach) jest usunięcie tych powtarzających się elementów i zrobienie z tego jakiejś funkcji/procedury.

0

Okej
Tak spróbuję zrobić :) Dziękuję bardzo jeszcze raz za merytoryczną pomoc!

1

I jak - czy udało Ci się coś pchnąć do przodu, czy nie miałeś czasu, żeby do tematu przysiąść?

0

Wiesz co - za dużo czasu nie miałem, ale próbowałem trochę. Niestety sposób na jaki wpadłem też pewnie jest mało dobry, ale tak

Stworzyłem procedurę Conjugation, która w jakiś sposób usprawnia to, ale to chyba jeszcze nie to co można by pochwalić

procedure TMainForm.Conjugation;
begin
  CheckedVerb := AnsiRightStr(Verb, 3);
  if (CheckedVerb = 'are') or (CheckedVerb = 'ere')
  or (CheckedVerb = 'ire') then
  begin
		Delete(Verb, L-2, 3);
  	lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + 'o');
  	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + 'i');
  	lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + 'iamo');
  end;
  	if CheckedVerb = 'are' then
    begin
      lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'a');
      lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ate');
      lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ano');
    end;
    if CheckedVerb = 'ere' then
    begin
    	lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'e');
    	lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ete');
    	lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ono');
    end;
    if CheckedVerb = 'ire' then
    begin
    	lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + 'e');
    	lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + 'ite');
    	lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + 'ono');
    end;
end; 

Próbowałem tez stworzyć tablice znaków i ładować do niej słowo i potem dodawać końcówki itd, ale jest wiele innych problemów, których w ten sposób nie ogarnę.

Myślę nad jakimś usprawnieniem tego, ale nie wiem czy wymyślę szybko coś lepszego :) Ale na bank będę próbował

2

Szczerze mówiąc to myślałem o trochę innym rozwiązaniu.

Po pierwsze - w Twoim pierwszym poście masz 3 razy powtórzone to samo - po każdym z trzechIF masz delete a potem 6 razy zmieniasz wartości różnych caption. Lepiej by było te captiony dać do osobnej procedury, która potem zostanie wywołana z parametrami. Coś w stylu ChangeCaptions('o', 'i', 'a', 'io'....) . Nie jest to rozwiązanie idealne, ale na razie nie ma co wchodzić na wyższe poziomy skomplikowania ;)

Taka uwaga techniczna - jeszcze trochę się doczepię do tych IF'ów. Obecnie masz zapisane to w postaci X := AnsiEndsStr('are', Verb); if X = true then. Po pierwsze - sprawdzając warunek przy IF nie musisz robić porównania. IF potrzebuje do działania wartości TRUE albo FALSE, ale przecież tą wartość masz już zapisaną w zmiennej X, więc równie dobrze możesz napisać if X then. Ale tak właściwie to po co wprowadzać zmienną X? Z tego co widzę, to nie robi ona niczego, poza zapisaniem wyniku zwróconego przez funkcję, w związk z czym zmienną X można całkowicie wyeliminować, a podanego kilka linii wyżej IF'a zapisać w postaci if AnsiEndsStr('are', Verb) then.....

A co do fragmentu "jest wiele innych problemów, których w ten sposób nie ogarnę" - napisz konkretnie co chcesz zrobić i z czym masz problem, a pewnie coś wyczarujemy :)

0

W tym nowym kodzie, który wrzuciłem (chodzi o tę procedurę Conjugation) całkowicie zrezygnowałem z tego AnsiEndsStr.
Użyłem procedury AnsiRightStr, która sprawdza 3 ostatnie znaki zmiennej Verb i potem w If'ie sprawdza czy było 'ere', 'are' czy 'ire'.

0

Owszem, zauważyłem, ale i tak napisałem o tych IF'ach w celu dydaktycznym ;)
W poprawionym kodzie zauważ, że i tak masz trzy razy powtórzone po 3 linijki, więc to mógłbyś wydzielić do osobnej procedury zgodnie z tym, co napisałem w poprzednim poście.

Plus powtarzam - jak chcesz to napisz konkretnie co chcesz zrobić i z czym masz problem - pewnie coś wykminimy :)

0

Dziękuję bardzo za Twoją pomoc jeszcze raz. Mam taki charakter trochę, że zanim konkretnie napiszę to lubię sam się męczyć z czymś dlatego pytam tutaj, ale nie oczekuję całego kodu :D

Mam takie pytanie, bo zastanawiam się. Czy jeżeli stosuje się procedury zamiast powtarzać linijki kodu tak jak zaproponowałeś to taki program działa też szybicej czy to tylko kwestia czytelności i łatwiejszego utrzymania programu? Oczywiście nie mówię, o moim, bo tutaj nie bardzo jest co przyspieszać, ale o jakiś większych projektach.

0

Z punktu widzenia wydajności to raczej różnicy nie odczujesz, głównie chodzi o łatwość (trudność?) czytania kodu przez programistę (zarówno autora, który wraca do tematu po roku, jak i przez obce osoby), a także o skalowalność i łatwość modyfikacji.

Na Twoim przykładzie - 2 razy sugerowałem. żeby powtarzające się czynności wyodrębnić. Powiedzmy, że z jakiegoś powodu fragment lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + 'o'); trzeba zmienić tak, aby zamiast LowerCase zrobić UpperCase. Obecnie musisz znaleźć w programie wszystkie miejsca, w których taki zapis się pojawił i je ręcznie przerobić. Natomiast w sytuacji, w której wydzielisz to do funkcji, która będzie w kilku miejscach w programie wywoływana, to wystarczy zmianę nanieść jeden raz w tej właśnie funkcji/procedurze. Jest to wygodniejsze, a także zmniejsza ryzyko przeoczenia któregoś z wystąpień poprawianego kodu.

0

No ma to sens :)
Dziś już nie mam możliwości poprawienia tego, ale jutro rano postaram się zasiąść do tego ewentualnie wieczorem na spokojnie.

0

A tak jeszcze w temacie prędkości działania - zasadniczo takimi tematami powinny się przejmować jedynie osoby tworzące programy, które wykonują dużo skomplikowanych obliczeń. W erze gigahercowych przynajmniej 4-rdzeniowych procesorów, do których jest podpięte kilka/kilkanaśćie albo i kilkadziesiąt GB RAM, te parę dodatkowych cykli CPU jest totalnie nieodczuwalnych. Nie ma najmniejszego sensu bawić się w optymalizacje aplikacji, bo tego nikt nie odczuje, a ten czas i energię lepiej poświęcić na bardziej przydatne zadania.

Oczywiście - dobrze jest pisać dobry, czysty, przemyślany i dobrze zaprojektowany kod, ale nie zmienia to faktu, że np. te kilka rzeczy, które Ci sugerowałem do poprawy w poprzednich postach nie będzie miało żadnego wpływu na wydajność aplikacji. Zresztą zasada jest taka, że kod, jeśli jest napisany bez błędów, to się raczej skompiluje i powinien działać, tak więc nie dba się o jego jakość dlatego, żeby zrobić dobrze kompilatorowi. Zamiast tego należy myśleć o tym, że ktoś za pewien czas będzie mógł to czytać i to tej osobie należy okazać jakąś litość i miłosierdzie ;)

1

Zrobiłem coś takiego. Nie wiem czy to miałeś na myśli, ale faktycznie lepiej to wygląda

procedure TMainForm.ChangeCaptions(A, B, C, D, E, F : String);
begin
	Delete(Verb, L-2, 3);
	lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + A);
	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + B);
	lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + C);
	lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + D);
	lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + E);
	lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + F);
end;

procedure TMainForm.Conjugation;
begin
  CheckedVerb := AnsiRightStr(Verb, 3);
  if (CheckedVerb = 'are') then
  begin
    ChangeCaptions('o', 'i', 'a', 'iamo', 'ate', 'ano');
  end;
  if CheckedVerb = 'ere' then
  begin
    ChangeCaptions('o', 'i', 'e', 'iamo', 'ete', 'ono');
  end;
  if CheckedVerb = 'ire' then
  begin
    ChangeCaptions('o', 'i', 'e', 'iamo', 'ite', 'ono');
  end;
end;   

Zastanawiam się teraz tylko jak będę robił kolejne reguły czy nie będzie problemu z edycją, ale pobawię się z tym :)

1

Dodałem jeden wyjątek.

procedure TMainForm.Conjugation;
begin
  { Wyjątek dla czasownikow zakonczonych na -care i -gare }
	CheckedVerb := AnsiRightStr(Verb, 4);
  if (CheckedVerb = 'care') or (CheckedVerb = 'gare') then
  begin
  	ChangeCaptions('o', 'hi', 'a', 'hiamo', 'ate', 'ano');
  end;

  { Czasowniki regularne }
  CheckedVerb := AnsiRightStr(Verb, 3);
  if CheckedVerb = 'are' then ChangeCaptions('o', 'i', 'a', 'iamo', 'ate', 'ano');
  if CheckedVerb = 'ere' then ChangeCaptions('o', 'i', 'e', 'iamo', 'ete', 'ono');
  if CheckedVerb = 'ire' then ChangeCaptions('o', 'i', 'e', 'iamo', 'ite', 'ono');
end;  

Tak to wygląda. Będę wciąż myślał jak to upraszczać :)

0

No zasadniczo właśnie o to mi chodziło, zadanie domowe Pan ładnie odrobił :) Całkowicie się z Tobą zgadzam, że w tej postaci jest to znacznie czytelniejsze, zajmuje mniej miejsca i wygląda bardziej profesjonalnie.

Jak szaleć to szaleć - idziemy za ciosem i poprawki robimy dalej :D

Teraz zamieniamy kilka następujących po sobie IF'ów na konstrukcję case of... - http://wiki.freepascal.org/Case :)

A co do sprawdzania listy słów będących wyjątkami - pierwsze, co mi przyszło do głowy (aczkolwiek nie jest to wcale optymalne rozwiązanie, zwłaszcza jak/jeśli tych słówek będzie więcej) to wrzucenie ich do tablicy, a następnie "przelecenie" przez nią i sprawdzenie, czy słówko w niej występuje. Docelowo możemy zrobić sobie pobieranie danych z jakiegoś SQL, więc wtedy lista słówek będzie trzymana w bazie, ale na chwilę obecną wpiszemy je "na sztywno" do kodu programu.

Najpierw wrzucamy gdzieś definicję tablicy z listą słówek nieregularnych. Można to dać gdzieś "na górze" kodu, w okolicach definicji klasy TForm1, aczkolwiek zmienne globalne są passe i ogólnie jest hejt na ich używanie ;) Dlatego listę słów możesz także umieścić chociażby w treści procedury, która zostanie wywołana w celu sprawdzenia, czy dane słówko jest regularne. Tablicę zrobiłem jako const, żeby przypadkiem nikt w niej nie namieszał, aczkolwiek jeśli z jakiegoś powodu będzie Ci to potrzebne, możesz śmiało zmienić jej rodzaj ze stałej na zmienną. Poniżej cała (jak widać - średnio skomplikowana) procedura, która sprawdza, czy słowo znajduje się na liście. Oczywiście - ten sposób się może sprawdzać w przypadku kilkunastu/kilkudziesięciu elementów, ale nie wyobrażam sobie pracy w ten sposób na większych ilościach danych. Dobra wiadomość jest taka, że jeśli z jakiegoś powodu numeracja indeksów tablicy (oraz wynikająca z tych numerów ilość elementów) nie będzie się pokrywać z ilością słów na liście, to kompilator wywali od razu błąd (jak nie wierzysz to możesz się pobawić i sam sprawdzić ;) )

procedure SprawdzNieregularnoscSlowka;

var JakasZmienna: string;
  CzyWystepuje: Boolean = FALSE;

const
 ListaSlowek : array [1..3] of string = ('raz', 'dwa', 'trzy');

begin
  for JakasZmienna in ListaSlowek do
      if (Form1.Edit1.Text = JakasZmienna) then CzyWystepuje := TRUE;

if CzyWystepuje then Form1.Button1.Caption:='JEST' else Form1.Button1.Caption:='BRAK';

end;

Nie wiem, czy sam na to wpadłeś, czy tak wyszło przypadkiem, ale w przedostatnim kodzie (czyli tym, w którym miałeś już powtarzające się operacje wydzielone do osobnej procedury) przy każdym IF miałeś begin ... end;. W kolejnym poście już tych beginów nie było. Jeśli celowo je usunąłeś to fajnie, a jeśli tak po prostu wyszło, to chciałem zaznaczyć, iż te beginy są niepotrzebne. Standardowo po if zostaje wykonana jedna instrukcja. Jeśli chcemy zawrzeć ich kilka (nie tylko po if, ta uwaga jest dość uniwersalna) w miejscu, w którym powinno być jedno polecenie, to "obejmujemy" te wszystkie polecenia klamrą begin .... end;. Kompilator traktuje wszystko zawarte w tej klamrze jako jedną komendę.

1

Oj to może od początku, bo sporo tego, a zanim napisałeś to dużo rzeczy już sam zrobiłem (z czego przyznam się jestem trochę dumny :P), jak np. to wyszukiwanie w tablicy tylko ja to zrobiłem tak.

Zmienna IreVerbs (czasowniki nieregularne zakonczone na -ire).

IreVerbs: Array[1..28] of String = (
  'agire', 'applaudire', 'assorbire', 'capire', 'chiarire', 'colpire','costruire',
  'favorire', 'ferire', 'finire', 'fiorire', 'fornire', 'guarire', 'impedire',
  'inghiottire', 'mentire', 'nutrire', 'patire', 'preferire', 'pulire', 'punire',
  'rapire', 'spedire', 'subire', 'tossire', 'tradire', 'ubbidire', 'unire');   

a w kodzie

  if CheckedVerb = 'ire' then
    If AnsiMatchStr(Verb, IreVerbs) = true then
      ChangeCaptions('isco', 'isci', 'isce', 'iamo', 'ite', 'iscono')
    else
    	ChangeCaptions('o', 'i', 'e', 'iamo', 'ite', 'ono'); 

Tyle, że ja to zrobiłem bez procedury, a po prostu jaką zmienną globalną i wyszkukiwanie przy pomocy AnsiMatchStr. Nie znałem konstrukcji for JakasZmienna in ListaSlowek do.

Co do tych Caseów to ja raczej ich unikam, bo nigdy nie jestem pewny czy ona może zawierać w sobie kolejne case'y, a obecnie dodałem kilka wyjątków i program wygląda tak

procedure TMainForm.ChangeCaptions(A, B, C, D, E, F : String);
begin
  Delete(Verb, L-2, 3);
	lblFirstSingularPresentIndicative.Caption := LowerCase(Verb + A);
	lblSecondSingularPresentIndicative.Caption := LowerCase(Verb + B);
  lblThirdSingularPresentIndicative.Caption := LowerCase(Verb + C);
	lblFirstPluralPresentIndicative.Caption := LowerCase(Verb + D);
  lblSecondPluralPresentIndicative.Caption := LowerCase(Verb + E);
  lblThirdPluralPresentIndicative.Caption := LowerCase(Verb + F);
end;

procedure TMainForm.Conjugation;
begin
  { Wyjątek dla czasownikow zakonczonych na -care i -gare }
	CheckedVerb := AnsiRightStr(Verb, 4);
  if (CheckedVerb = 'care') or (CheckedVerb = 'gare') then
  ChangeCaptions('o', 'hi', 'a', 'hiamo', 'ate', 'ano');

  CheckedVerb := AnsiRightStr(Verb, 3);
  if CheckedVerb = 'are' then
    { Funkcja pobiera 5 i 4 znak od końca i sprawdza czy te znaki ciag "ci" lub
    	"gi" i jeżeli tak to dodaje odpowiedni koncowki 														}
    if (MidStr(Verb, L-4, 2) = 'ci') or (MidStr(Verb, L-4, 2) = 'gi') then
    ChangeCaptions('o', '', 'a', 'amo', 'ate', 'ano')
    else
    { Odmiana regularna	}
  	ChangeCaptions('o', 'i', 'a', 'iamo', 'ate', 'ano');
  end;

  if CheckedVerb = 'ere' then ChangeCaptions('o', 'i', 'e', 'iamo', 'ete', 'ono');
  if CheckedVerb = 'ire' then
    If AnsiMatchStr(Verb, IreVerbs) = true then
      ChangeCaptions('isco', 'isci', 'isce', 'iamo', 'ite', 'iscono')
    else
    	ChangeCaptions('o', 'i', 'e', 'iamo', 'ite', 'ono');
end;  

Tak jak widać tutaj np. w If'ie z "are" jest podinstrukcja, która sprawdza czy 4 i 5 znak od końca to "ci" lub "gi" i jeśli tak to dodaje inne końcówki. Nie wiem jak teraz to oceniasz

0

Napiszę w nowym poście żeby nie robić zamieszania w tym poprzednim.

Dodałęm taką funkcję

function TMainForm.IreVerbsChecker: Boolean;
const
	IreVerbs: Array[1..28] of String = (
  'agire', 'applaudire', 'assorbire', 'capire', 'chiarire', 'colpire','costruire',
  'favorire', 'ferire', 'finire', 'fiorire', 'fornire', 'guarire', 'impedire',
  'inghiottire', 'mentire', 'nutrire', 'patire', 'preferire', 'pulire', 'punire',
  'rapire', 'spedire', 'subire', 'tossire', 'tradire', 'ubbidire', 'unire');
begin
  if AnsiMatchStr(Verb, IreVerbs) = true then
  Result := true;
end;  

Ona co prawda nie sprawdza nieregularnych rzeczy, ale robi to napisałem w poprzednim poście.
w programie funkcja jest użyta tak

If IreVerbsChecker = true then
      ChangeCaptions('isco', 'isci', 'isce', 'iamo', 'ite', 'iscono')
0

No widzę, że sam sobie nieźle radzisz. Szkoda, że mało osób na forum jest na takim samym poziomie samodzielności i zaangażowania, co Ty :(

Co do sposobu sprawdzania czy słowo jest w tablicy - każdy jest dobry, tak czy siak "sprawdzarka" musi przelecieć przez każde słowo z tablicy, więc wydajność jest podobna (a zresztą, jak pisałem parę postów wcześniej, przy obecnych prędkościach procesorów, te kilka dodatkowych cykli jest totalnie nieodczuwalne).

Dobrze, że wydzieliłeś sprawdzenie do osobnej funkcji, a nie pozostawiłeś w kodzie. Niby nie robi to w chwili obecnej większej różnicy, ale jakby pojawiła się konieczność wprowadzania zmian - tak będzie znacznie łatwiej. Poza tym lepiej się to czyta - w kodzie masz odwołanie do funkcji sprawdzającej, czy jakiś warunek został spełniony. Jeśli chcesz sprawdzić, jak jest ten mechanizm zbudowany - to przechodzisz do treści funkcji/procedury. Jeśli natomiast analizujesz kod, który potrzebuje wykonać sprawdzenia (a jednocześnie sama struktura mechanizmu sprawdzającego nie jest Ci potrzebna do szczęścia) to masz jednego prostego if i wszystko jest jasne.

Żeby nie było za słodko - poza chwaleniem muszę też Cię lekko opieprzyć :P Chodzi o fragment

if AnsiMatchStr(Verb, IreVerbs) = true then .....

Czy wiesz, o co mi chodzi? Pisałem o tym w tym poście - https://4programmers.net/Forum/1558289

1

Dzięki za miłe słowo ;)

Co do błedu to wiem o co chodzi. Z przyzwyczajenia już piszę zawsze if X = true then :P Poprawione na If IreVerbsChecker then

Zrobię mały update. Nie wiem za bardzo jak zabrać się za tego SQLa, dlatego na razie przygotowałem taką funkcję


function TMainForm.IreVerbsChecker: Boolean;
var
  A: String;
  IreVerbsFile: TextFile;
begin
  AssignFile(IreVerbsFile, 'IreVerbs.txt');
  Reset(IreVerbsFile);
  while not Eof(IreVerbsFile) do
  begin
    ReadLn(IreVerbsFile, A);
    if A = Verb then
    Result := true;
  end;
  CloseFile(IreVerbsFile);
end;

Czyli jednym słowem zrezygnowałem z tej tablicy, którą miałem i teraz program sprawdza czy dany wyraz występuje w pliku IreVerbs.txt i jeśli tak to dodaje odpowiednią końcówkę. Jest to pewnie dalekie od ideału rozwiązanie, ale na razie nic innego nie wymyślę :)

0

W temacie SQL - rzuć proszę okiem na https://www.itwriting.com/blog/articles/a-simple-delphi-wrapper-for-sqlite-3 - tam jest ładnie wyjaśnione (wraz z przykładami) jak można dosłownie w kilku liniach skorzystać z SQLite.

A następnie masz udoskonaloną wersję w/w rozwiązania, stworzoną przez Ararat, czyli twórcę Synapse (chyba najlepszy pakiet do obsługi sieci w Pascalu) - http://www.ararat.cz/doku.php/en:sqlitewrap . Jak sami piszą "This is very simple Sqlite 3 wrapper for Delphi and FreePascal" - więc nie powinieneś mieć żadnych problemów, żeby odpalić to w Lazarusie.

A jeszcze mam pytanie do samej logiki tego, co zrobiłeś/opisałeś w poprzednim poście. Program sprawdza, czy dane słowo znajduje się w pliku i w zależności od tego, co ustali, traktuje je jako regularne albo nie. Ale czy w wypadku nieregularnych nie trzeba wpisać gdzieś poszczególnych form? W przypadku słów z regularną odmianą, po prostu dodaje się odpowiednie końcówki. Ale nieregularne mogą być totalnie dowolne, w związku z czym chyba w pliku, poza listą słów, powinny być określone ich formy dla poszczegółnych odmian/przypadków/cokolwiek ;)

I jeszcze jedna uwaga -nie wiem, czy nie byłoby bezpieczniej, jakbyś w podanej przez siebie procedurze lekko przerobił fragment if A = Verb then - ja bym zarówno A jak i Verb przerobił na małe/wielkie litery. Obecnie, jeśli w pliku masz słowo "Stefan", a użytkownik wpisze "stefan" albo "STEFAN" to powyższe sprawdzenie nie załapie, że chodzi o to samo słowo.

0

Hej.
Spróbuje dziś ogarnąć tego SQLa i dam znać jak będą postępy :D

Co to funkcji to już wyjaśniam. W języku włoskim III koniugacja to czasowniki z -ire i one dzielą się na 2 typy jeszcze (tak w skrócie), mianowicie regularne czyli np czasowniki partire i w takim wypadku odcinamy końcówkę -ire i po prostu dodajemy kolejno:

[io] parto
[tu] parti
[Lei/lei/lui] parte
[noi] partiamo
[voi] partite
[loro] partono

ale jest bardzo duża część czasowników, które prócz tych końcówek mają jeszcze, w niektórych osobach tzw. wrostek -isc- i wygląda to tak, np czasownik finire

[io] finisco
[tu] finisci
[Lei/lei/lui] finisce
[noi] finiamo
[voi] finite
[loro] finiscono

Nie ma na to reguły i takie czasowniki trzeba na pamięć wykuć dlatego lista wydaje się jedynym rozsądnym rozwiązaniem :) Dlatego tutaj moje funkcja sprawdza czy czasownik znajduje się w pliku i jeśli tak to dodaje końcówki z -isc-.

Co do ostatniego punktu to w miejscu, gdzie użytkownik wpisuje czasownik mam taką linię

Verb := Trim(LowerCase(VerbEdit.Text));

Także czasownik może być wpisany jako FiNiRE, a funkcja i tak skróci go i poprawi na małe litery, a takie znajdują się w pliku.

Edit // Przejrzałem to co mi podesłałeś, ale niestety zupełnie czarna magia dla mnie to jest i nie mam pojęcia jak miałbym to wykorzystać u siebie. Muszę trochę bardziej zrozumieć o co w tym chodzi żeby brać się za takie rzeczy

0

Jeżeli chcesz to mogę Ci dać kilka przykładów działania z sqlite - podstawowy odczyt, zapis itp.

A co do nieregularnych - myślałem, że będzie to zupełnie freestyle, a z tego co piszesz to wynika, że w sumie ich odmiana jest regularna, tylko może przebiegać jedna z dwóch ścieżek. Mam rację, czy coś zle zrozumiałem?

0

Jeżeli mógłbyś to poproszę - może wtedy łatwiej ruszę :)

Te czasowniki z Ire są po części nieregularne właśnie, natomiast są czasowniki całkowicie nieregularne jak np essere, którego odmiana to sono, sei, è, siamo, siete, sono i tutaj już regułka nie zadziała. Trzeba by stworzyć właśnie bazę z listą takich słów i ich odmiana

0

No ok, teraz mam wizję jak to zrobić. O ile w przypadku wyboru jednego z dwóch sposobów odmiany sam plik tekstowy jest względnie ok, to średnio się to sprawdzi w przypadku pełnej dowolność. Tutaj trzeba będzie dane słowa wpisać na sztywno we wszystkich postaciach.

Postaram się wieczorem coś napisać w zakresie sql. Widząc twoje podejście, podejrzewam że wolisz jakieś przykłady a nie gotowca. Mam rację?

0

Jasne, że tak. Jak starczy mi czasu to może sam do wieczora to rozgryzę i uda mi się jakoś to napisać. W tej chwili nie bardzo np. wiem jak mógłbym do bazy danych zaimportować tę listę czasowników z tą odmianą -ire + -isc-, bo nie chciałbym tego robić ręcznie, bo to bez sensu chyba trochę. ;)

0

A czy ta lista to twoja produkcja, czy masz to z netu pobrane? Ogólnie to musisz pobrać po kolei każdy wyraz z listy (analogicznie jak to chciałes robić kilka postów wyżej) i wsadzić go do bazy ;) dobrze jest jeszcze sprawdzić, czy już go w bazie nie ma, można ewentualnie ustawić na kolumnie UNIQUE, ale tutaj coś mi świta (aczkolwiek to tylko takie wrażenie, muszę potem sprawdzić) że sqlite miało z tym kiedyś lekkie problemy.

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