Polskie litery w konsoli - Pascal

0

Dobra, to już mój ostatni temat. Proszę w nim o poprowadzenie krok po kroku, a nie odesłanie do linku. Ten jeden raz i wychodzę, więcej wam głowy nie zawracam. Chodzi o to, że jeżeli wpiszę kod: writeln('ąęłść') w Lazarusie, to po skompilowaniu wyświetlają się jakieś krzyżyki, niemieckie litery itd.

Na prawdę proszę o wyjaśnienie krok po kroku, co muszę zrobić.

0

No tak panicz żąda artykułu...
rzecz jasna taki powstał pozostaje kwestia jego odszukania.
Jeśli napiszesz mi pod jakimi hasłami szukałeś rozwiązania swojego problemu (przynajmniej 5 różnych zapytań do wyszukiwarki) to zrobię ci listę wyników, które trafiają w to o co chcesz zapytać i to z konkretnymi odpowiedziami.

0

Próbowałem różne kombinacje:
-Zmiana kodowanie pascal
-kodowanie konsola
-polskie litery konola/lazarus/pascal
-strona kodowa pascal
itd., takich wyszukiwań nie było 5, a co najmniej kilkanaście.

2

Możesz do uses dodać FileUtil i używać funkcji UTF8ToConsole np:

 writeln(UTF8ToConsole('ąęłść'));

Ponieważ ten unit wymaga LCL trzeba wejść w Project -> Project Inspector tam Add zakładka New Requirement i wybrać LCL i nacisnąć Create New Requirement.

0

Zmiana kodowanie pascal za mało konkretów
kodowanie konsola za mało konkretów brak języka, nie mówiąc o IDE, plus za słowo "konsola"
polskie litery konola/lazarus/pascal literówka, ale już na 3 wyniku jest temat który odpowiada na twoje pytanie.
strona kodowa pascal zbyt ogólne - strona kodowa czego?

tu jest to czego szukasz Brak polskich znaków w Lazarusie

0

@lucasp17: dobra, trzymam/y Cię za słowo. Czyli każdy kolejny Twój temat, jaki tutaj dojrzę wywalam do kosza, ok? Bo w ogóle nie wykazujesz się posiadniem komponentu TBrain oraz korzystaniem z TGoogle. Pokombinował byś chwilę sam najpierw i poszukał, a nie ze wszystkim lecisz na forum. Nie od tego są fora żeby bez własnego wkładu żądać ze wszystkim pomocy. Co do pytania spróbuj taki kod dla tekstów ANSI:

function OEMWrite(AnsiText : string) : string;
begin
  Result := '';
  if AnsiText <> '' then
  begin
    SetLength(Result, Length(AnsiText));
    AnsiToOEM(PChar(AnsiTexT), PChar(Result));
  end;
end;
0
kAzek napisał(a):

Możesz do uses dodać FileUtil i używać funkcji UTF8ToConsole np:

 writeln(UTF8ToConsole('ąęłść'));

Ponieważ ten unit wymaga LCL trzeba wejść w Project -> Project Inspector tam Add zakładka New Requirement i wybrać LCL i nacisnąć Create New Requirement.

Dziękuję bardzo. Idealna odpowiedź. Krótko wszystko wyjaśnione i działa prawidłowo. Pierwszy raz dostałem na tym forum tak dobrą odpowiedź.

Co prawda nie wiem czy jest to rozwiązanie idealne i jedyne, ale mi wystarcza, chociaż uciążliwe może być za każdym razem dopisywanie UTF8ToConsole.

0
lucasp17 napisał(a):

Dziękuję bardzo. Idealna odpowiedź. Krótko wszystko wyjaśnione i działa prawidłowo. Pierwszy raz dostałem na tym forum tak dobrą odpowiedź.

Doprawdy?
Uruchamianie programu na pełnym ekranie

0

I według Ciebie
Dokładnie to samo masz zrobić:

Znajdujesz w gogle gdzie się znajduje UTF8ToConsole (w którym unicie)
Znajdujesz ten unit w folderze Lazarusa
Dołączasz kolejny folder.

jest dobra odpowiedzią? Nie rozumiem z tego kompletnie nic. Co mam szukać, jak etc. Jedynie punkt 3 miał sens, bo to pokazałeś wcześniej. Jednak może nie zauważyłeś, tu w dwóch zdaniach mam napisane krok po kroku co zrobić. W DWÓCH ZDANIACH.

0

Po wstępie ja Tobie napiszę jednym zdaniem, co jeżeli zrobisz to będziesz sobie radził samodzielnie bez pytania co chwile na forum i liczenia na gotowce. Bo tak będziesz bładził po omacku i nie rozumiał nawet tak oczywistej podpowiedzi Dragona. Uwaga piszę :P Uważnie przeczytaj kurs/y z podstawami języka, który/e sobie obierasz za cel, a link/i do ów/ych wygooglujesz, jeżeli tylko poświęcisz chwilę na naukę oraz poszukiwania.

2
lucasp17 napisał(a)

chociaż uciążliwe może być za każdym razem dopisywanie UTF8ToConsole.

Nadpisz sobie Writeln-a:

Procedure Writeln(const Text: String);
Begin
 System.Writeln(UTF8ToConsole(Text));
End;

Procedure Writeln(const Fmt: String; const Args: Array of Const);
Begin
 Writeln(SysUtils.Format(Fmt, Args));
End;

Co prawda będziesz musiał wywoływać ją nieco inaczej (tę drugą funkcję), ale zawsze wygodniej od wklejania wszędzie UTF8ToConsole:

Writeln('Ciąg znaków: %s | liczba całkowita: %d | liczba zmiennoprzecinkowa: %f', [ZmiennaString, ZmiennaInteger, ZmiennaExtended]);

(array of const delphi oraz delphi format w Google, jeżeli nie masz pojęcia, dlaczego i jak to działa)

0

Niestety musiałem wrócić. Prawda teraz polskie litery konsola wyświetla prawidłowo, ale czy jest możliwość żeby je też czytała prawidłowo? Konkretnie chodzi mi o to, że przez readln sczytuję np. imię, które ma polskie znaki. Później chciałbym stworzyć z folder, który będzie tym imieniem i plik w którym imię będzie się znajdowało. Niestety w tym momencie pojawiają się inne znaczki. Da się to jakoś rozwiązać?

0

A czy nie przyszło Tobie do głowy, że jeżeli istnieje funkcja AnsiToOEM to za pewne będzie i jej odwrotność? Pomyśl Ty czasami i sprawdzaj w Google zanim o coś spytasz!

program Project2;

{$APPTYPE CONSOLE}

uses
  Windows;

function AnsiWrite(OEMText : string) : string;
begin
  Result := '';
  if OEMText <> '' then
  begin
    SetLength(Result, Length(OEMText));
    OEMToAnsi(PChar(OEMText), PChar(Result));
  end;
end;

function SaveTextToFile(AFileName : string; InStr : string) : boolean;
var
  OutFile : THandle;
  BytesWritten : DWORD;
  OutFileSize : Integer;
begin
  OutFile := CreateFile(PChar(AFileName), GENERIC_WRITE, FILE_SHARE_READ,
    nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  Result := OutFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    OutFileSize := Length(InStr);
    WriteFile(OutFile, InStr[1], OutFileSize, BytesWritten, nil);
    CloseHandle(OutFile);
  end;
end;

var
  S : string;
begin
  Write('Wpisz cokolwiek: ');
  Readln(S);
  SaveTextToFile('test.txt', AnsiWrite(S));
end.

Edit: ubiegając Twoje kolejne 45 tysięcy pytań. Dla FPC oczywiście powyższy kod musi zawierać dyrektywą kompilatora {$MODE DELPHI}. I zdaje się, ze akurat tam APPTYPE jest na ogół zbędne.

2

ConsoleToUTF8

0
olesio napisał(a):

A czy nie przyszło Tobie do głowy, że jeżeli istnieje funkcja AnsiToOEM to za pewne będzie i jej odwrotność? Pomyśl Ty czasami i sprawdzaj w Google zanim o coś spytasz!

program Project2;

{$APPTYPE CONSOLE}

uses
  Windows;

function AnsiWrite(OEMText : string) : string;
begin
  Result := '';
  if OEMText <> '' then
  begin
    SetLength(Result, Length(OEMText));
    OEMToAnsi(PChar(OEMText), PChar(Result));
  end;
end;

function SaveTextToFile(AFileName : string; InStr : string) : boolean;
var
  OutFile : THandle;
  BytesWritten : DWORD;
  OutFileSize : Integer;
begin
  OutFile := CreateFile(PChar(AFileName), GENERIC_WRITE, FILE_SHARE_READ,
    nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  Result := OutFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    OutFileSize := Length(InStr);
    WriteFile(OutFile, InStr[1], OutFileSize, BytesWritten, nil);
    CloseHandle(OutFile);
  end;
end;

var
  S : string;
begin
  Write('Wpisz cokolwiek: ');
  Readln(S);
  SaveTextToFile('test.txt', AnsiWrite(S));
end.

Edit: ubiegając Twoje kolejne 45 tysięcy pytań. Dla FPC oczywiście powyższy kod musi zawierać dyrektywą kompilatora {$MODE DELPHI}. I zdaje się, ze akurat tam APPTYPE jest na ogół zbędne.

Co do tego, to chyba nie do końca jest to rozwiązanie problemu. Zresztą ja też chyba nie napisałem wszystkiego. Mój program tworzy powiedzmy bazę danych. Może nie jest to najlepsze rozwiązanie, żeby coś takiego robić na plikach tekstowych, ale nie w tym rzecz. Ja chciałbym aby po wpisaniu writeln(plik, 'Imię') w odpowiednim pliku pojawił się napis Imię z polską literką. Kolejny punkt to wpisanie wartości podanej przez użytkownika, a więc coś w stylu podanego kodu, ale ja w jednym pliku mam kilkanaście zmiennych do wpisania, a więc to chyba nie do końca tak zadziała. Kolejna już sprawa to stworzenie folderu z imieniem i nazwiskiem, np. Adam Małysz. W nazwisku jest polska litera, czy da się utworzyć folder?

0
_13th_Dragon napisał(a):

ConsoleToUTF8

To rozwiązanie jest bliższe tego co chcę osiągnąć. Ale w ten sposób nie jestem w stanie stworzyć folderu. Zresztą pliku też w ten sposób nie stworzę.

0

Operacje plikowe pod windows obsługiwane w unicode.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363855%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365430%28v=vs.85%29.aspx
Pamiętać o upewnieniu się że twoje środowisko wywołuje wersje z W na końcu.

Jeżeli nie korzystasz z WinAPI to http://lazarus-ccr.sourceforge.net/docs/rtl/sysutils/forcedirectories.html powinno używać normalnego UTF8.

1

Piszesz, że nie idzie utworzyć folderu z polskimi znakami diaktyrycznymi. To się najpierw zastanów co chcesz zrobić. A nie piszesz, że zależy Tobie koniecznie na UTF8. Kod jaki podałem powyżej, jeżeli wpiszesz po prompcie łąkę i potwierdzisz enterem, to w pliku będziesz miał łąkę normalnie widoczne pod Notatnikiem w kodowaniu jako ANSI, a nie kodowanie znaków jak dla konsoli. Jeśli chcesz koniecznie mieć kodowanie nazw pliku jako UNICODE, to masz przecież mnóstwo funkcji WinAPI w odmianach z W na końcu, jak CreateFileW. Ogarnij Ty najpierw chlopie WinAPI w takim razie, a i ogólnie podstawy w końcu.

I niby piszesz pod FPC, ale ja fileutil widzę tylko pod Lazarusem, który mam 64 bitowy. A FPC oczywiście aktualizowałem w wersji Win32. Ale żeby i to zadziałalo pod Lazarusem to trzeba pododawać paczki komponentów, ogólnie cudować strasznie. Jeżeli już musisz tak cudować to ja bym zrobił coś w ten deseń, jak poniżej. A i mogę się mylić, ale zarówno ukochana przez Ciebie funkcja do UTF8 jak i OemToCharW potrzebują stringów, a przynajmniej ta druga wymaga jako źródła PChar, także na logikę skoro konwertuje do UNICODE to raczej z typów znakowych, które mogą przechowywać jedynie ANSI.

program test;

{$MODE DELPHI}

uses
  Windows;

function WideWrite(OEMText : string) : WideString;
begin
  Result := '';
  if OEMText <> '' then
  begin
    SetLength(Result, Length(OEMText));
    OemToCharW(PChar(OEMText), PWideChar(Result));
  end;
end;

function OEMWrite(AnsiText : string) : string;
begin
  Result := '';
  if AnsiText <> '' then
  begin
    SetLength(Result, Length(AnsiText));
    AnsiToOEM(PChar(AnsiText), PChar(Result));
  end;
end;

var
  WS : WideString;
begin
  Write(OEMWrite('Podaj nazwę folderu do utworzenia: '));
  Readln(WS);
  CreateDirectoryW(PWideChar(WideWrite(WS)), nil);
  if GetLastError <> 0 then
  begin
    if GetLastError = ERROR_ALREADY_EXISTS then
    begin
      Writeln(OEMWrite('Folder o takiej nazwie już istnieje!'));
    end
    else
    begin
      Writeln(OEMWrite('Nieprawidłowa nazwa dla folderu!'));
    end;
    Readln;
  end;
end.

EDIT: ewentualnie jeżeli już tak kombinujesz, to żeby się upewnić czy aby na pewno tworzę wszystko jak nalezy. Wlazłem sobie na Wikipedię, skopiowałem z hasła Korea jej oryginalny zapis, wkleiłem w Notatniku do pliku i zapisałem jako folder.txt z kodowaniem UNICODE. Słabo ogarniam zagadnienia kodowania, ale do polskich znaków, dla polskiego użytkownika docelowego, który ma za pewne system w polskim lub angielskim języku, spokojnie wystarczyło by Tobie kodowanie jakie oferuje notatnik pod UNICODE. Nie wiem po co zaraz UTF8. Ale na upartego też można, tylko pewnie funkcję zapisu do pliku trzeba by przerobić. Ja już się w to nie zagłębiałem. Tak czy inaczej. Tworzy mi elegancki folder o nazwie 한국, 조선. Zresztą zobacz na screen w załączniku do tego posta.

program test2;

{$MODE DELPHI}

uses
  Windows;

function OEMWrite(AnsiText : string) : string;
begin
  Result := '';
  if AnsiText <> '' then
  begin
    SetLength(Result, Length(AnsiText));
    AnsiToOEM(PChar(AnsiText), PChar(Result));
  end;
end;

function FileSeek(Handle, Offset, Origin : integer) : integer;
begin
  Result := SetFilePointer(THandle(Handle), Offset, nil, Origin);
end;

function WideReadTextFromFile(AFileName : WideString; var OutStr : WideString) : boolean;
var
  S : string;
  B1, B2 : Byte;
  BytesRead : DWORD;
  SrcFile : THandle;
  SrcFileSize : Int64;
  IsBomPresent : boolean;
begin
  OutStr := '';
  IsBomPresent := False;
  SrcFile := CreateFileW(PWideChar(AFileName), GENERIC_READ,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Result := SrcFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    SrcFileSize := GetFileSize(SrcFile, nil);
    if SrcFileSize > 0 then
    begin
      ReadFile(SrcFile, B1, SizeOf(B1), BytesRead, nil);
      if SrcFileSize > 1 then
      begin
        ReadFile(SrcFile, B2, SizeOf(B2), BytesRead, nil);
        IsBomPresent := (B1 = $FF) and (B2 = $FE);
      end;
    end;
    if IsBomPresent then
    begin
      SrcFileSize := SrcFileSize - SizeOf(B1) - SizeOf(B2);
    end
    else
    begin
      FileSeek(SrcFile, 0, FILE_BEGIN);
    end;
    SetLength(OutStr, SrcFileSize);
    if not IsBomPresent then
    begin
      SetLength(S, SrcFileSize);
      ReadFile(SrcFile, S[1], SrcFileSize, BytesRead, nil);
      OutStr := S;
    end
    else
    begin
      ReadFile(SrcFile, OutStr[1], SrcFileSize, BytesRead, nil);
    end;
    CloseHandle(SrcFile);
  end;
end;

var
  WS : WideString;
begin
  if WideReadTextFromFile('.\folder.txt', WS) then
  begin
    MessageBoxW(GetForegroundWindow, PWideChar(WS), 'Testy', 0);
    CreateDirectoryW(PWideChar(WS), nil);
    if GetLastError <> 0 then
    begin
      if GetLastError = ERROR_ALREADY_EXISTS then
      begin
        Writeln(OEMWrite('Folder o takiej nazwie już istnieje!'));
      end
      else
      begin
        Writeln(OEMWrite('Nieprawidłowa nazwa dla folderu!'));
      end;
      Readln;
    end;
  end;
end.
0

Nie wiem jak działa ten kod, nie potrafię go w całości zrozumieć, ale starałem się coś z niego wyciągnąć, ale każda moja próba kończył się inną nazwą niż oczekiwana. Przede wszystkim wydaje mi się, że podany przez Ciebie kod sczytuję nazwę folderu z pliku tekstowego, które sam ustaliłeś kodowanie. Mi chodzi o to, aby to użytkownik podawał nazwę.

Przerzuciłem się w tym momencie na tworzenie aplikacji w lazarusie. Nie wiem jak mi to wyjdzie, ale warto spróbować. Choć już na początku pojawił się mi problem, bo o ile w konsoli mogłem wyświetlić tyle napisów ile zostało obliczone, to nie wiem w jaki sposób zrobić aby ilość label, albo edit była różna. Ale nie o tym w tym temacie. Chciałbym aby tworzył się folder taki jaki poda użytkownik. Miałem nadzieję, że po ominięciu konsoli to się uda, jednak folder który się tworzy również nie jest taki jak powinien. A próbowałem to zrobić: createdir(edit1.text);

0

Użyj: CreateDirectoryW.
CreateDirdziała jeszcze wyłacznie dla kompatybilności.

0

Czego nie rozumiesz konkretnie w moim kodzie? Jest on banalny jak konstrukcja cepa. Wszystkie funkcje WinAPI masz wyjaśnione na MSDN. Także żadnej magii tutaj nie ma. Lazarus to też ok rozwiązanie, a folder stworzysz tak, jak pokazałem. O ile wiem kodowanie stringów z kontrolek edycyjnych pod Lazarusem powinno być w UNICODE. Ale jak pisałem do tworzenia folderu z polskimi znakami diakrycznymi spokojnie nadają się łańcuchy przechowujące znaki ANSI.

Także funkcja CreateDirectoryA też Ci takowy utworzy. Tylko jeżeli kontrolka edycyjna przechowuje AnsiStringi czego teraz nie sprawdzę, bo jestem w pracy i siedzę na Androidzie. To po prostu używasz wspomnianej funkcji z A na końcu, do stworzenia folderu i jako pierwszy parametr podajesz PChar(Edit1.Text). I nie wiem o co Tobie chodzi z tą ilością Labeli oraz Editów. Kładziesz na formatkę tyle ile potrzeba i je oprogrqamowujesz. Oczywiście nie ma co też przesadzać robiąc z interface'u programu jakieś tysiąc elementowe puzzle.

0

Jak już pisałem ja się do tego pewnie źle zabieram. Znam w pascalu kilka funkcji, ale taki kod jaki napisałeś jest dla mnie dziwnie wyglądający. Ja takiego nigdy nie napisałem. Pierwszą rzeczą której nie rozumiem są nazwy. Być może jest to oczywiste. Ja ustalam sobie nazwy zmiennych tak, że zawsze wiem co jest co. Jako przykład IsBomPresent. Nie mam pojęcia czym to jest i do czego będzie służyć. Kolejna sprawa to typ THandle. Czytałem coś na ten temat, ale nie wiem po co się tego używa. Może faktycznie programowanie nie dla mnie. Ja myślę w sposób taki w jaki pisze się strony internetowe. Jak napiszę wyświetl tu, to tu się to wyświetla. Nie ma tam żadnych uchwytów itd. Oczywiście też chodzi mi o same podstawy HTML/CSS.

Ale dobrze jak już zacząłem to skończę pisać czego nie zrozumiałem. Jeżeli nie wiem co to za typ, to nie wiem też jaką wartość przyjmuje SrcFile.
Result := SrcFile <> INVALID_HANDLE_VALUE; Myślałem, że to może mieć wartość true albo false. A tu jest jakaś nierówność. Podobnie tu: IsBomPresent := (B1 = $FF) and (B2 = $FE);

Nie rozumiem też tego: FileSeek(SrcFile, 0, FILE_BEGIN); pierwszy parametr to ty THandle, a w funkcji jest on integerem. A właściwie nawet nie wiem po co ta funkcja znalazła się w kodzie. Przyjmuje tylko jakąś wartość i nic więcej nie robi.

Ale najgorsze jest to, że ja nie wiem w którym miejscu tak na prawdę program czyta nazwę z pliku. Folder jest zapewne tworzony poprzez CreateDirectoryW(PWideChar(WS), nil); Ale przecież WS nie ma żadnej wartości jest tylko zadeklarowane w zmiennych jako WideString.

Dziękuję Wam za chęć pomocy. Na prawdę. Ale jeżeli to są podstawy to bardzo się co do tego myliłem. Nie wiem też dlaczego matura rozszerzona z informatyki była "rozszerzona", bo tam moja wiedza w zupełności wystarczyła. A jak już pisałem ja się posługiwałem do tej pory tylko pętlami, małymi procedurami i funkcjami, działaniami matematycznymi, obsługą plików tekstowych poprzez assign(plik, sciezka). Wydawało mi się, że wiele, przynajmniej w samym Pascalu można w ten sposób zrobić, jednak ten kod odbiega znacznie od tego co ja wiem. Nie krzyczcie, opisałem czego nie rozumiem, po prostu wydawało mi się to zawsze prostsze.

A jeszcze wracając do Lazarusa, po użyciu CreateDirectoryA i podaniu napisu łąka utworzył się folder: Ĺ‚Ä…ka. A jeśli chodzi o ilosć labeli i editów to chodziło mi o to, by mogła się zmieniać w zależności od czegoś... np. ilości podanej przez użytkownika. Albo wypisanie danych z pliku. W tym momencie jeszcze nie wiem jak to zrobić aby wyświetlić kilka wierszy danych. Potrafię tylko tyle ile wcześniej sam zadeklaruję, a wiadomo, ze baza danych się powiększa, a więc ta ilość wyświetlana też powinna być ustalana automatycznie. Ale jak pisałem jestem na początku, po kilku godzinach oglądania tutoriali i próbowania. Na razie za dużo zrobić nie potrafię, raczej tyle samo co w samym pascalu, aczkolwiek bez pętli, które by wyświetlały coś na ekranie. Właśnie o czymś takim piszę powyżej. Korzystałem głównie z .Gdybym teraz miał sam zrobić podobny program, to nie miałbym problemu. Ale w tym momencie moja wiedza nie gwarantuje mi zaspokojenie moich potrzeb.

1
lucasp17 napisał(a)

Nie wiem czym jest strumień bajtów, albo wielobajtowe kodowanie znaków

Przeczytaj te dwa pojęcia na głos.
Najlepiej kilka razy.

strumień bajtów

http://pl.wikipedia.org/wiki/Strumień_danych
W dużym uproszczeniu: tablica bajtów.

wielobajtowe kodowanie znaków

Na przykład UTF-8 - zawsze tam, gdzie jeden znak kodowany jest za pomocą więcej niż jednego bajta.
Przykładowo znaku Ϫ nie zakodujesz za pomocą jednobajtowego ASCII i musisz użyć innego zestawu danych. W UTF-8 ten jeden znak ma przyporządkowane dwa bajty: 0xCF 0xAA.

Wikipedia mówi znacznik kolejności bajtów i dalej coś co mi nic nie mówi, niestety

Wiesz, co to big endian i little endian?

3
lucasp17 napisał(a):

Jak już pisałem ja się do tego pewnie źle zabieram. Znam w pascalu kilka funkcji, ale taki kod jaki napisałeś jest dla mnie dziwnie wyglądający. Ja takiego nigdy nie napisałem.

Musisz poznać treść kursów z podstawami. Wtedy będziesz co i jak, bo tak będziesz błądzić po omacku. I to nie jest na siłe trucie Tobie, czytaj kursy. Tylko na prawdę poznając podstawy będziesz wiedział co i jak.

Pierwszą rzeczą której nie rozumiem są nazwy. Być może jest to oczywiste. Ja ustalam sobie nazwy zmiennych tak, że zawsze wiem co jest co. Jako przykład IsBomPresent. Nie mam pojęcia czym to jest i do czego będzie służyć.

To już wyjaśnili poprzednicy. Nazwa zmiennej "mówi wszystko" - sprawdza ona czy w pliku jest obecny znacznik BOM, co jest konieczne przy plikach z kodowaniem UNICODE. Jest to dokładniej omówione na Wikipedia. Linka już dostałeś. Także poczytaj.

Kolejna sprawa to typ THandle. Czytałem coś na ten temat, ale nie wiem po co się tego używa. Może faktycznie programowanie nie dla mnie. Ja myślę w sposób taki w jaki pisze się strony internetowe. Jak napiszę wyświetl tu, to tu się to wyświetla. Nie ma tam żadnych uchwytów itd. Oczywiście też chodzi mi o same podstawy HTML/CSS.

To nie czytaj "coś na ten tamat", tylko poczytaj dokładnie na MSDNie co i jak. Typ THandle, to odpowiednik ceplusplusowych typów Handle i przechowuje on uchwyty zwracane przez różne funkcje WinAPI.

Tutaj na przykład pozwala operwać poprzez uchwyt na pliku. Tak jak do operacji na kontrolkach wizualnych jest używany typ w tym samym zakresie przedziału HWND. Poczytaj na MSDN dokumentację tej funkcji WinAPI, to dowiesz się co zwraca. Oraz co z tym dalej można zrobić. A i Delphi to nie HTML. Jest o wiele łatwiesze imo na start. A poza tym na ogół prosty kod nie wygląda jak strona HTML inaczej pod każdą przegląrką inaczej, jak i również pod innymi rozdzielczościami jeszcze inaczej. Uważam, ze porównywanie z HTML jest tutaj raczje nietrafione. To zupełnie inne języki, a i oczywiście do czego innego też mają służyć.

Ale dobrze jak już zacząłem to skończę pisać czego nie zrozumiałem. Jeżeli nie wiem co to za typ, to nie wiem też jaką wartość przyjmuje SrcFile.
Result := SrcFile <> INVALID_HANDLE_VALUE; Myślałem, że to może mieć wartość true albo false. A tu jest jakaś nierówność.

Zmienna SrcFile jest jak widzisz typu THandle. I może przyjąć wartość takiej stałej. Poczytaj dokumentacje tej funkcji API, to zobaczysz co może zwracać jeżeli się operacja tworzenia/odczytu pliku się nie powiedzie na przykład ze względu na złą nazwę czy lokalizację pliku albo problem z prawami dostępu.

A własne funkcje pod FPC/Lazarus z dyrektywą kompilatora MODE DELPHI mogą zwracać swoje wyniki poprzez "ukrytą zmienną" Result, bo normalnie musielibysmy pisać CalaNazwaFunkcji := ...;. I pisząc takie coś, od razu obsługuje i rezultar funkcji i sprawdzenie poprawności. To znaczy jest to bardziej przejrzysty zapis i logiczny, niż pisanie if SrcFile <> ... then begin Result := False; ... i tak dalej. I tutaj mamy zwracanie True/False.

To tak jak przy konstrukcji sprawdzania warunków if. Jeżeli tam coś pomieszasz, możesz otrzymać komunikat błądu od kompilatora Error: Boolean expression expected. Ponieważ właśnie oczekiwane są wartości porównań booleanowskich. Czyli jeżeli coś jest typu boolean, to zapis typu IsPersonAdult := Age >= 18; jest prawidłowy, jeżeli mamy takie zmienne i są one odpowiedniego typu. Także typ boolean, może być również wynikiem powówńan logicznych odpowiednimi operatorami, wtedy zwraca właśnie True lub False. Poczytaj kurs z podstawami, to ogarniesz takie rzeczy bez problemu :) Na prawdę.

Podobnie tu: IsBomPresent := (B1 = $FF) and (B2 = $FE);

Tutaj jest sprawdzenie czy kolejne dwa odczytane bajty z pliku mają odpowiednie wartości hex. Zgodnie z tym co opisuje Wikipedia. Oczywiście mozna to poprawić tak by obsługiwalo pozostałe znaczniki. Ja na szybko skupiłem się tylko na tym od UNICODE. I nie czytałem nic o BOM, tylko podpatrzyłem pod Hex Edytorem co tam się zapisuje przed właściwym tekstem i tyle :)

Nie rozumiem też tego: FileSeek(SrcFile, 0, FILE_BEGIN); pierwszy parametr to ty THandle, a w funkcji jest on integerem. A właściwie nawet nie wiem po co ta funkcja znalazła się w kodzie. Przyjmuje tylko jakąś wartość i nic więcej nie robi.

To nieprawda, ze ta funkcja nic nie robi. Poczytaj sobie na MSDN opis funkcji SetFilePointer. Ustawia ona znacznik od którego czytać dane z pliku. A funkcja FileSeek jest wzięta ze źródeł VCL od Delphi 7 i modułu SysUtils. Może jest tam drobna nieścisłośc, bo pierwszy jej parametr powinen być zadeklarowany jako typ THandle. Ale ponieważ zarówno on jak i typ integer są liczbowe. A później w definicji funkcji jest rzutowanie na THandle, to nie ma problemów.

Kod jest taki, gdyż założyłem że jeżeli plik nie będzie z oczekiwanym BOM'em, to nalęży odczytać zawartość pliku od jego początku i zwrócić jako tekst ANSI. Gdyż po co nam tekst bez dwóch pierwszych znaków. A wiadomo, że funkcje zapisujące i odczytujące z pliku, przesuwają pozycje odczytu o sukcesywnie odczytaną/zapisaną ilośc bajtów. Nawet te przestarzałe "potworki" jak BlockRead czy BlockWrite.

Ale najgorsze jest to, że ja nie wiem w którym miejscu tak na prawdę program czyta nazwę z pliku. Folder jest zapewne tworzony poprzez CreateDirectoryW(PWideChar(WS), nil); Ale przecież WS nie ma żadnej wartości jest tylko zadeklarowane w zmiennych jako WideString.

No najgorsze właśnie, bo nie poznałeś podstaw języka. To nieprawda, że zmienna WS nic nie zawiera, ponieważ inaczej otrzymywał byś ostrzeżenie od kompilatora, a także utworzenie folderu nie było by możłiwe. Zobacz co zwraca funkcja WideReadTextFromFile jako swój drugi parametr. Jest tam "magiczne" słowo kluczowe var, które tak jak out potrafi zwracać potrzebne nam rzeczy w parametrze, jeżeli przekażemy tam zmienną.

Jakbyś poczytał kurs z podstawami, do czego po raz kolejny szczerze namawiam, to byś poznał i te zagadnienie opisane tutaj Out i wszystko było by jasne dla Ciebie :)

Dziękuję Wam za chęć pomocy. Na prawdę. Ale jeżeli to są podstawy to bardzo się co do tego myliłem. Nie wiem też dlaczego matura rozszerzona z informatyki była "rozszerzona", bo tam moja wiedza w zupełności wystarczyła. A jak już pisałem ja się posługiwałem do tej pory tylko pętlami, małymi procedurami i funkcjami, działaniami matematycznymi, obsługą plików tekstowych poprzez assign(plik, sciezka). Wydawało mi się, że wiele, przynajmniej w samym Pascalu można w ten sposób zrobić, jednak ten kod odbiega znacznie od tego co ja wiem. Nie krzyczcie, opisałem czego nie rozumiem, po prostu wydawało mi się to zawsze prostsze.

Może i WinAPI nie jest zagadnieniem podstawowym, ale warto prędzej czy późnej je poznać.

Co do matury, to jak rozumiem planuejsz ją zdawać z informatyki. No ok, ale to radzę poznać język w którym chcesz pisać na niej zadania. Ja tylko rozwiązałem sobie większość zadań pod Delphi 7 z tej z przed dwóch lat. Może lepiej wybierz jako dodatkowy przedmiot do zdawania coś innego, a programowanie traktuj jako hobby. Ja maturę zdawałem daaawnooo temu i to nie z informatyki. Ale dlaczego się nazywa rozszerzoną, to nie wiem. Po prostu tak musi być, ale pięć godzin na klepanie po łębkach może być za mało. Chyba, że się sporo poćwiczy wcześniej i ogarnie się temat w tym czasie, żeby móc uzyskać jak najwięcej punktów. A i tak dziwi mnie dopuszczenie tam jako narzędzia do rozwiązywania zadan Accessa, którego na studium policelanym nigdy nie ogarniałem, ale techika informatyka uzyskałem. Ale zaliczyłem to ledwie na trójkę, jeżeli dobrze pamiętam. I nigdy więćej do Accesa nie wracałem. Wedle mnie ktoś kto chce być dobrym programistą w przyszłości, powinien ogarniać dobrze jakiś język programowania, a nie klilanie reklacji w tym czymś. Takie jest moje zdanie :)

A jeszcze wracając do Lazarusa, po użyciu CreateDirectoryA i podaniu napisu łąka utworzył się folder: Ĺ‚Ä…ka.

Teraz się upewniłem. Pod 64 bitowym Lazarusem. Przekazujesz string UTF8 do funkcji oczekującej ANSI, także dlatego masz krzaczki. Zrób tak, jak poniżej i będzie ok. Folder o nazwie łąkę utworzył się mi bez problemu z prawidłową nazwą.

  CreateDirectoryA(PChar(Utf8ToAnsi(Edit1.Text)), nil);

A jeśli chodzi o ilosć labeli i editów to chodziło mi o to, by mogła się zmieniać w zależności od czegoś... np. ilości podanej przez użytkownika. Albo wypisanie danych z pliku. W tym momencie jeszcze nie wiem jak to zrobić aby wyświetlić kilka wierszy danych.

Poczytaj o dynamicznym tworzeniu komponentów. Ale najpierw poczytaj też koniecznie podstawy języka. Później bierz się za robienie baz danych. Według mnie baza danych napisana jako wprawki, powinna mieć stałą ilość pól. Do przechowywania baz ze zmienną ilością pól można używać plików XML, a później zainteresować się na przykłąd SQL'em i jeżeli baza ma być offline to SQLite, tam sobie możesz trzymać spokojnie zmienną ilość pól i tabel.

Potrafię tylko tyle ile wcześniej sam zadeklaruję, a wiadomo, ze baza danych się powiększa, a więc ta ilość wyświetlana też powinna być ustalana automatycznie. Ale jak pisałem jestem na początku, po kilku godzinach oglądania tutoriali i próbowania. Na razie za dużo zrobić nie potrafię, raczej tyle samo co w samym pascalu, aczkolwiek bez pętli, które by wyświetlały coś na ekranie.

Spoko, zgłęb podstawy i będzie ok. Tylko na prawdę więcej samodzielności i chęci kombinowania z kodem. Posłużę się tutaj przykładem Użytkownika @Patryk27. Mam nadzieję, że się nie obrazi ;) Popatrz na Jego dzieło. Kompilator języka skryptowego. Pisany również w Obiektowym Pascalu. Dla mnie zagadnienie, którego nie chciało by mi się zgłębiać bez potrzeby. Maszyna wiertualna, parser wyrażeń, do tego własne IDE. Gdyby On podchodził jak Ty teraz i oczekiwał tylko suchych przykładów. Nic by nie googlował, nie kombinował sam. To by w życiu nic takiego nie napisał. Trzeba po prostu chcieć i się nie poddawać. Jakbyśmy wszyscy tylko smarowali na forach z byle pierdółkami, nie kombinując nic sami, to nikt by nie ruszył z miejsca i nie napisał prostego Hello World w czymkolwiek ;)

Takze pisząc o googlowaniu i kombinowania do bółu mam na myśli na prawdę zaangażowanie w próbę samodzielnego rozwiązania problemów. Wiadomo są fora, ale powinno się traktować je jako na prawdę ostatecznośc. Tymbardziej pisząc w języku tak prostym do ogarnięcia na start, jakim jest Obiektowy Pascal. A i oczywiśćie wspominałeś, że wolałeś korzystac z konstrukcji dla mnie rodem trochę z Turbo Pascala 7.0, jak Assign. Oczywiście można, ale lepiej spróbować zainteresować się prędzej czy później chociaż podstawami funkcji WinAPI.

Tutaj często ludzie postują, oczywiście nie wdziale Newbie, bo po co pisać do właściwego działu. Lepiej kazać innym przenosić to później, "bo tak". I na przykład modzą zapis linijek z memo poprzez AssignFile i użycie TTextFile. No jasne, a po co pomyśleć, pogooglować i korzystać z TSringList albo ze pochodnych klasy TStream. Skoro już piszemy pod VCL/LCL, to po co uparcie wtrącać w to konstrukcje z TP 7. Jeżeli już posiłkujemy się gotowymi klasami w postaci kontrolek wizualnych, to korzystajmy z pozostałych rozwązań też dostępnych przy okazji z całym dobrodziejstwem inwentarza.

Właśnie o czymś takim piszę powyżej. Korzystałem głównie z .Gdybym teraz miał sam zrobić podobny program, to nie miałbym problemu. Ale w tym momencie moja wiedza nie gwarantuje mi zaspokojenie moich potrzeb.

Spoko, to takie tutoriale dla leniwych. Mozna się nimi posiłkowac, ale radzę je traktować jako ciekawostka. Lepiej coś poczytać z kursów, pokombinować samodzielnie, googlować za przykładami kodów, których jest cała masa.

Wiadomo super hiper kalulatorem można się pochwalić kolegom z piaskownicy czy gimnazjum. Ale i tak przy początkach nauki, nic lepszego oraz bardziej funkcjonalnego niż ten Windowsowy z pewnością nie napiszemy. I nie powinniśmy do tego aspirować. Tracąc czas na pierdółki. Ale co kto woli. Wiadomo, fajnie że ludzie robią tutki video. Kiedyś nie istniały za szybkie łącza, ogromne przestrzenie dyskowe serwerów czy YouTube. Także o fajne lekcje video było ciężko. Ale tak jak papier Internet też jest w stanie wszystko przyjąć i bywa powiedzmy cierpliwy. To później trafiają tam i takie śmieci, z których można się tylko pośmiać. Moim ulubionym filmikiem jest oczywiście ten: jako przerywnik na koniec i rozluźnienie.

To już nie chodzi o to że nagrywa to jakiś gimbus o inteligencji galaretki. Ale człowiek szukając na prawdę naiwnie materiałów o inżynierii wstecznej po Polsku, natrafia na coś takiego. Toż to chce się urwać mu od Internetu by więcej takiego czegoś nie wrzucał.

Na koniec a propos bazy. Zapoznaj się z moim kodem i exekiem w załączniku tego posta. Pisane dawno, na szybko, może kod nie jest za idealny. Ale przykład prostej bazy jest. Pisane pod Delphi 7, ale pewnie przy odrobinie chęci można to przekonwertować pod Lazarusa. Moze się to Tobie do czegoś przyda. I nie używam tutaj żadnych rozwiązań rodem z TP 7, tylko klas do stworzenia bazy w prostym pliku typowanym. Może się to Tobie do czegoś przyda, jako materiał poglądowy. Bo tak lubisz przykłady ;)

I sorry za rozpisanie się. Początkowo post ten był i tak dłuższy. Zawierał linki do stron z dokumentacjami funkcji na MSDN. Ale te sobie już sam wygoogluj. Ponieważ pod koniec pisania posta, po prostu jak to często na tym forum niestety bywa. Coś się przy kombinacji cofania po treści kursorem strzałki, przeskoczyło i wszystko poszło się paść. Także pisałem od nowa, wklejając co chwila całość do Notatnika i zapisując do pliku. Pewnie to jakaś zemsta, ktorej dokonał @Adam Boduch w Coyote, żeby chyba zemścić się może za masową eksterminacje jajek na Wielkanoc ;)

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