Zmienna długość łańcucha w tablicy

Zmienna długość łańcucha w tablicy
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0

Witam wszystkich, mam dość nietypowy pomysł / problem; Otóż chodzi o to, że projektuję klasę, która korzysta z dynamicznej dwuwymiarowej tablicy przechowującej tekst w postaci łańcucha typu ShortString; Niestety przechowując w tablicy np. nazwy lokalnych plików (bez nazw katalogów) wiadome jest, że nie potrzeba 256 znaków na to, wystarczyło by 50; Ale nie mogę tego zaprogramować na sztywno, potrzebuję w konstruktorze pobrać ilość znaków jaka będzie przypadać na każde pole, ale tylko raz, a później (w dalszej części konstruktora) w jakiś sposób utworzyć główną tablicę, która będzie właśnie przechowywać dane typu String[podana_długość];

Czy ma ktoś pomysł jak to zaprogramować? Bardzo proszę o podpowiedź;

Stworzona tablica musi być niewidoczna (sekcja private);


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
MA
  • Rejestracja:ponad 16 lat
  • Ostatnio:11 dni
0

A próbowałeś z array of array of Char?

Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

po co kombinować.
wystarczy zwykły string, który w zależności od wersji delphi jest tym samym co ansistring albo unicodestring.

string ma dynamicznie alokowaną pamięć.

problem nie istnieje.

edytowany 1x, ostatnio: Azarien
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
Azarien napisał(a)

string ma dynamicznie alokowaną pamięć.

Racja, ma dynamicznie przydzielany odszar pamięci, ale właśnie chcę zmienić ze String na krótszy łańcuch;

Może po kolei; Tablica ta jest dwuwymiarowa, stąd można podczas korzystania z utworzonego wcześniej obiektu zmieniać jej rozmiar (zarówno pierwszego jak i drugiego wymiaru) odpowiednimi metodami; Ale gdy tablica posiada np. pięć kolumn i tysiąc wierszy metoda do odczytu pojedynczej komórki nie zwraca jej wartości mimo tego, że komórka o podanym adresie nie dość, że istnieje to jeszcze posiada jakąś wartość różną od pustego łańcucha; Nie wiem dlaczego tak się dzieje, ale obliczałem teoretyczny rozmiar tablicy w bajtach i nie jest aż tak duża - każda komórka przyjmowała łańcuch o długości trzech znaków; Z resztą metoda ta już nie odczytywała komórki o adresie [4][290], gdzie 4 to indeks kolumny, a 290 wiersza;

Niestety musiałem zaprojektować tablicę tak, by najpierw podawało się indeks kolumny (czyli 4), a później wiersza (tu 290) a AFAIK powinno być na odwrót; Inaczej nie mógłbym w ogóle korzystać z tablicy, ponieważ dopuszczana jest możliwość, gdy wiersze nie istnieją, a kolumny tak:

Kopiuj
Length(Tablica) //zwraca ilość kolumn
Length(Tablica[0]) //zwraca ilość wierszy pod warunkiem, że Length(Tablica) zwraca wartość większą od 0

Ilość wierszy mogę odczytywać w ten sposób, ponieważ Tablica[0] istnieje zawsze, gdyż nie ma możliwości usunąć wszystkich kolumn, musi zostać co najmniej jedna; Jeżeli tablica jest pusta (tzn. nie posiada żadnych wierszy) musi być możliwość odczytu ilości kolumn, czyli Length(Tablica).

Wracając do pytania nie wiem, czy metoda nie odczytuje wartości pojedynczej komórki dlatego właśnie, że przeszkadza w czymś dynamiczne przydzielanie miejsca w pamięci dla łańcuchów typu String czy jest jakaś inna przyczyna; W każdym razie pamięci RAM na pewno mi nie brakuje;

Czy statyczna długość łańcucha może wyeliminować ten błąd czy to nie tu jest bubel? Czy zmiana typu danych przechowywanych w tablicy rozwiąże ten problem? Bo jeżeli nie to dlaczego tak się właśnie dzieje?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

Racja, ma dynamicznie przydzielany odszar pamięci, ale właśnie chcę zmienić ze String na krótszy łańcuch;

krótszy niż ile?
piszesz że nie chcesz marnować pamięci:

Niestety przechowując w tablicy np. nazwy lokalnych plików (bez nazw katalogów) wiadome jest, że nie potrzeba 256 znaków na to, wystarczyło by 50; Ale nie mogę tego zaprogramować na sztywno

otóż typ string da ci dokładnie taki efekt: stringi zajmujące tyle pamięci co potrzeba. nie trzeba nic dodatkowo kombinować.

Z resztą metoda ta już nie odczytywała komórki o adresie [4][290], gdzie 4 to indeks kolumny, a 290 wiersza;
zamieniłeś kolejność indeksów. stąd pewnie bierze się twój błąd.

edytowany 1x, ostatnio: Azarien
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
Azarien napisał(a)

otóż typ string da ci dokładnie taki efekt: stringi zajmujące tyle pamięci co potrzeba. nie trzeba nic dodatkowo kombinować.

W takim razie skoro jest o wiele lepszy niż kombinowanie z ich długością to bardzo się cieszę;

Azarien napisał(a)

zamieniłeś kolejność indeksów. stąd pewnie bierze się twój błąd.

Masz jakiś pomysł jak ustawiając indeksy odwrotnie móc odczytać ilość kolumn gdy tablica jest pusta (czyli nie ma wierszy)?

PS: W sumie w pierwszych wersjach klasy podstawowym typem danych w tablicy był łańcuch String; Myślałem, że to on sprawia problemy i zmieniłem to, ale nie miało to znaczenia;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
cimak
  • Rejestracja:około 22 lata
  • Ostatnio:ponad 9 lat
  • Postów:1668
0
Furious Programming napisał(a)

Ale gdy tablica posiada np. pięć kolumn i tysiąc wierszy metoda do odczytu pojedynczej komórki nie zwraca jej wartości mimo tego, że komórka o podanym adresie nie dość, że istnieje to jeszcze posiada jakąś wartość różną od pustego łańcucha;

a co zwraca blad, "krzaczki"...? sprawdz czy oby na pewno odwolujesz sie do tej komorki, bo czasem wystarczy literowka jakas.
pamietaj o indeksowaniu tablic od zera.
powodem moze tez byc ze wpisujez dane da tablicy pod nieprawidlowym adresem -co nie wyrzuci bledu- i w efekcie masz namieszane w pamieci programu.

Furious Programming napisał(a)

W każdym razie pamięci...

W każdym bądź razie :)

edytowany 2x, ostatnio: cimak
Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

Masz jakiś pomysł jak ustawiając indeksy odwrotnie móc odczytać ilość kolumn gdy tablica jest pusta (czyli nie ma wierszy)?

jak nie ma wierszy to nie ma „kolumn”. coś jest nie tak z twoim projektem.
zdecyduj się, czy chcesz dwuwymiarową tablicę znaków, czy tablicę stringów.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
cimak napisał(a)

a co zwraca blad, "krzaczki"...?

W tym rzecz, że nic, pusty łańcuch, brak wartości; Nie ma żadnego błędu, nie wyskakuje AV;

cimak napisał(a)

sprawdz czy oby na pewno odwolujesz sie do tej komorki, bo czasem wystarczy literowka jakas.

Sprawdzam indeksy czy istnieją w tablicy; Na dodatek jeżeli pobieram ilość kolumn i wierszy oraz wyświetlam ich wartości np. tak:

Kopiuj
  ...

var
  iC, iR: Integer;
begin
  ....

  iC := Length(Tablica); //pobranie ilości kolumn
  iR := Length(Tablica[0]); //pobranie ilości wierszy

  MessageBox(PChar('Columns: ' + IntToStr(iC) + #10'Rows: ' + IntToStr(iR)), 'Counts', MB_OK);

  ...

zawsze pobierana jest właściwa ilość zarówno kolumn jak i wierszy; W ten sam sposób sprawdzam indeksy przed pobraniem wartości z danej komórki, więc nie mam pojęcia dlaczego zawsze przy indeksie wiersza większym niż mniej więcej 290 zwraca pusty łańcuch;

cimak napisał(a)

pamietaj o indeksowaniu tablic od zera.

A da się inaczej przy tablicach dynamicznych? :)

cimak napisał(a)

powodem moze tez byc ze wpisujez dane da tablicy pod nieprawidlowym adresem -co nie wyrzuci bledu- i w efekcie masz namieszane w pamieci programu.

Nie ma możliwości odwołać się do komórki, która nie istnieje, bo metody służące do wpisywania danych do komórek są zabezpieczone pod kątem właśnie nieprawidłowych indeksów;

cimak napisał(a)

W każdym razie

Czy coś źle napisałem? :P

Azarien napisał(a)

jak nie ma wierszy to nie ma „kolumn”.

Właśnie; Chciałbym, by była możliwość odczytu ilości kolumn podczas gdy nie ma wierszy; Jeżeli zamienię indeksy - tej mozliwości nie będzie;

Azarien napisał(a)

coś jest nie tak z twoim projektem.

Dlaczego? Chcę tylko, by klasa była funkcjonalna;

Azarien napisał(a)

zdecyduj się, czy chcesz dwuwymiarową tablicę znaków, czy tablicę stringów.

Jestem zdecydowany; Potrzebuję przechowywać łańcuchy o dowolnej długości tylko chciałem użyć zamiast String typu 'array of Char'; W rezultacie deklaracja tablicy wyglądała by tak: Tablica: array of array of array of Char;; Wtedy długość każdej komórki (czyli array of Char) ustawiałbym ręcznie podczas wpisywania danych;

Dlaczego tak zadałem pierwsze pytanie? Ponieważ myślałem, że problem tkwi właśnie w korzystaniu z dynamicznych dwuwymiarowych tablic w połączeniu z łańcuchem zmiennej długości, lecz problem wcale ich nie dotyczy;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

W rezultacie deklaracja tablicy wyglądała by tak: Tablica: array of array of array of Char;

twoim problemem jest nie wyrażanie się w jasny sposób. teraz nagle się okazuje, że chciałbyś trójwymiarową tablicę znaków, czy tam dwuwymiarową tablicę stringów.

pokazujesz też za mało kodu. ani razu do tej pory nie pokazałeś jak definiujesz tablicę.

być może chodzi ci o array of array of string? nie będziemy wiedzieć, póki nie wyrazisz się jaśniej.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
pytanie tematu napisał(a)

Otóż chodzi o to, że projektuję klasę, która korzysta z dynamicznej dwuwymiarowej tablicy przechowującej tekst w postaci łańcucha typu ShortString;

Więc jak można zadeklarować taką tablicę?:

Kopiuj
Tablica: array of array of ShortString;

Czy to nie to samo co:

Kopiuj
Tablica: array of array of array of Char;

Teoretycznie tak, tyle że w drugim przypadku muszę ręcznie ustalać rozmiar tablicy stanowiącej komórkę (czyli array of Char to przecież w teorii to samo co String);

Azarien napisał(a)

twoim problemem jest nie wyrażanie się w jasny sposób.

Dzieje się tak dlatego, ponieważ ciężko mi dokładnie wytłumaczyć problem, a poza tym nie opiszę problemu tak, by każdy zrozumiał; Zawsze ktoś ma jeszcze jakieś wątpliwości; Wybaczcie za niejasności;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

nie, array of char to nie to samo co string. co ci się w stringu nie podoba? nie on jest źródłem problemu, tylko to:

ponieważ ciężko mi dokładnie wytłumaczyć problem, a poza tym nie opiszę problemu tak, by każdy zrozumiał

obawiam się, że sam nie rozumiesz co chcesz osiągnąć.

string jest ciągiem znaków. nie trzeba ręcznie nadawać mu wielkości przez setlength (choć na upartego można). większość rzeczy dzieje się automatycznie:
dynamiczne przydzielanie i zwalnianie pamięci zależnie od aktualnej długości przechowywanego tekstu. optymalizacja jest posunięta do tego stopnia, że zwykłe przypisanie stringa do stringa s:=t; wcale nie kopiuje całości danych, a jednak magicznie działa. z całą pewnością string jest lepszy i wygodniejszy od własnoręcznych wynalazków.

string[n] gdzie n to liczba w zakresie 1..255 jest dużo mniej sprytny. nie ma dynamicznie przydzielanej pamięci: zajmuje cały czas tyle samo bajtów (dokładnie n+1) i może przechowywać maksymalnie n znaków, czyli w najlepszym wypadku 255.

shortstring oznacza to samo co string[255]

edytowany 4x, ostatnio: Azarien
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
Azarien napisał(a)

nie, array of char to nie to samo co string.

Wolverine napisał(a)

Prawidlowe choc troche to mylace, string to tablica charow, idac dalej, jest to po prostu tablica...

http://4programmers.net/Delphi/Typy_danych

W takim razie Wolverine też się myli, a mimo to nikt mu uwagi nie zwrócił od 2005 roku;

delphi.about.com napisał(a)

Short String

Simply put, Short String is a counted array of (ANSII) characters, with up to 255 characters in the string. The first byte of this array stores the length of the string.

I ten, kto napisał ten artykuł także...?

Azarien napisał(a)

obawiam się, że sam nie rozumiesz co chcesz osiągnąć.

Ja napisał(a)

Dlaczego tak zadałem pierwsze pytanie? Ponieważ myślałem, że problem tkwi właśnie w korzystaniu z dynamicznych dwuwymiarowych tablic w połączeniu z łańcuchem zmiennej długości, lecz problem wcale ich nie dotyczy;

Wytłumaczyłem, dlaczego taka jest treść tematu; Potrzebuję wyjaśnienia, dlaczego nie mogę odczytać komórki o adresie wiersza większym niż mniej więcej 290; Metody są odpowiednio zabezpieczone przez przeciekiem;

EDIT: Azarien, nie tłumacz mi czym w ogóle jest typ String bo dobrze o tym wiem; Ma bardzo dużo zalet właśnie dlatego, że dynamicznie przydziela pamięć itd itd... Wspomniałem już co najmniej dwa razy, że myślałem, że dynamiczne przydzielanie pamięci dla każdego łańcucha gdzieś w czymś przeszkadza i dlatego nie odczytywało wartości komórek z wysokim indeksem wierszy; Pytałem się znajomego nauczyciela i taką dał mi wskazówkę, więc pytam; Dopiero jak skończyłem modyfikację klasy zamieniając typ String na ShortString upewniłem się, że to nie tu tkwi problem; Typ danych nie ma z tym nic wspólnego; No ale temat już był kilka dni wcześniej napisany więc musiałem się poprawić i zmienić pytanie;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
Zobacz pozostałe 5 komentarzy
pelsta
Pewnie uważasz, że LongWord i LongInt to też inne typy niemalże tylko z nazwy, bo obsługa jest taka sama. Ty w ogóle nie rozumiesz zagadnienia typów danych więc dyskusja jest bezcelowa.
flowCRANE
Chodzi Ci o zajętość pamięci? Jest różnica, nie upieram się że nie ma, dlatego pisałem, że teoretycznie korzysta się tak samo (prócz ustawiania długości tablicy), w praktyce jest już inaczej; Poza tym LongWord i LongInt to inna sprawa, bo ten pierwszy przyjmuje wartości nieujemne, a drugi może przyjmować ujemne; Pod względem String i tablicy Char'ów mają ten sam zakres danych, który stanową znaki;
Misiekd
@cimak nie bardzo wiem o co Ci chodzi z tym ręcznym ustawianiem długości. Jak zrobisz tak var s: string; s := '123'#0'456'; to Length(s) zwróci Ci 7. I w tej zmiennej (czy też jak wolisz w pamięci) będzie zapisane te siedem znaków. #0 kończy się PChar. Co do różnic to jeśli var a, b, c: array of Char nie da się zrobić tak a := 'abc' ani tak b := 'def' ani tak c := a + b; Nie da się też porównać np. tak a < b. String to w brew pozorom NIE JEST ALIAS NA TYP array of Char!!!!
cimak
@Misiekd - po raz kolejny Dzieki! :) z tym #0 to mi switalo w glowie ale najwyrazniej nie tam gdzie trzeba.
flowCRANE
Nie wspomniałem nigdzie, że String to alias typu array of Char; W teorii to dwie tablice, w praktyce zupełnie inna obsługa; Możemy wrócić do tematu?
cimak
  • Rejestracja:około 22 lata
  • Ostatnio:ponad 9 lat
  • Postów:1668
0

moze napisz po prostu od czego maja byc te kolumny i wiersze? wytlumacz dokladnie do czego chcesz tego uzyc...?

Furious Programming napisał(a)
cimak napisał(a)

W każdym bądź razie

Czy coś źle napisałem? :P

http://poradnia.pwn.pl/lista.php?szukaj=%22w+ka%BFdym+b%B1d%BC+razie%22&kat=18

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0

cimak, jak myślisz do czego można użyć takiej tablicy? Na przykład jako czegoś na kształt Excel'a, przeznaczenia konkretnego nie ma; To tak jak z komponentem ListBox - można z niego zrobić notatnik, WordPad'a, dowolną listę czy menu;

cimak napisał(a)

cimak:
W każdym razie

PWN napisał(a)

Ta pierwsza konstrukcja jest potoczna i uchodzi za kontaminację (skrzyżowanie) konstrukcji w każdym razie z bądź co bądź.

Piszę i mówię w języku potocznym, urzędowy mnie nie interesuje;

PWN napisał(a)

Zaimki Twój, Ci, Ciebie w listach czy pamiętnikach piszemy dużą literą.

Wszędzie, a sporo osób na tym forum pisze małą literą, a to brak szacuknu; Ale jakoś nikt nie robi z tego afery; Tak samo jak zaczynanie zdania od małej litery, pisanie bez znaków dialektycznych, nie wstawianie znaków interpunkcyjnych itd... Nie zaczynajmy dyskusji na temat poprawnej polszczyzny, bo nie o to chodzi w tym wątku;

cimak napisał(a)

moze napisz po prostu od czego maja byc te kolumny i wiersze?

Te kolumny i wiersze mają być od tablicy, będą pobierane przez odpowiednie właściwości w klasie; Jeżeli chodzi o to, czym będzie ta tablica, to mogę powiedzieć, że tabelą zawierającą dowolne ciągi znaków; To tak jak Excel może posiadać dowolne ciągi znaków w swoich komórkach, tak ta tablica też; Ogólnie rzecz biorąc (nie szukaj w PWN :P) ilość kolumn i wierszy może się przydać do czegokolwiek; W klasie są metody do eksportowania i importowania tablic dwuwymiarowych i mogą się przydać do ustawienia wielkości tablicy lokalnej, którą będzie się podawało w parametrze metody i właśnie z niej będą kopiowane dane do głównej tablicy w mojej klasie; Wykorzystanie nie ma znaczenia, ważne jest dla mnie to, by była taka możliwość; To tak jak w obiekcie z klasy TStrings nie jest ustalone przeznaczenie właściwości Count - można ją wykorzystać do sprawdzania ilości itemów lub do wykorzystania w pętli jako ostatni indeks itemu równy Count - 1; O to mi chodzi;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
cimak
  • Rejestracja:około 22 lata
  • Ostatnio:ponad 9 lat
  • Postów:1668
0
Furious Programming napisał(a)
Azarien napisał(a)

jak nie ma wierszy to nie ma „kolumn”.

Właśnie; Chciałbym, by była możliwość odczytu ilości kolumn podczas gdy nie ma wierszy; Jeżeli zamienię indeksy - tej mozliwości nie będzie

nie wiem czy dobrze rozumiem...
jesli mowimy o kolumnach i wierszach, to logiczne wydaje sie, ze dla kazdego wiersza sa te same kolumny - tak jak wspomnianym excel'u.
a z tego co piszesz to juz sam nie wiem czy dla kazdego wiersza tyle samo kolumn czy kazdy wiersz sie rzadzi swoimi prawami...?
napisz sobie osobna aplikacje testowa do obslugi array of array of string, a pozniej to przenies do swojego programu.

edytowany 1x, ostatnio: cimak
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
cimak napisał(a)

nie wiem czy dobrze rozumiem...
jesli mowimy o kolumnach i wierszach, to logiczne wydaje sie, ze dla kazdego wiersza sa te same kolumny - tak jak wspomnianym excel'u.
a z tego co piszesz to juz sam nie wiem czy dla kazdego wiersza tyle samo kolumn czy kazdy wiersz sie rzadzi swoimi prawami...?

Powoli, bo teraz ja Ciebie nie rozumiem...

Chodzi o to, że tak jak wspomniałem w Excel'u jest możliwa taka sytuacja, że tabela jest pusta (czyli nie ma wierszy), a mimo to jest możliwość sprawdzenia ile jest kolumn; Tak samo jest tu - jeżeli zadeklaruję tablicę tak, że pierwszy indeks oznacza wiersz, a drugi kolumnę:

Tablica[Wiersz][Kolumna]

to w momencie, gdy długość pierwszego wymiaru jest równa 0, czyli funkcja Length(Tablica) zwróci 0, nie mam możliwości odczytać długości drugiego wymiaru tą samą funkcją, bo wtedy Length(Tablica[0]) nie istnieje; Dlatego indeksy ustawione są na odwrót, by w razie ilości wierszy równej 0 (czyli funckja Length(Tablica[0]) zwraca 0) jest możliwość odczytania ilości kolumn tą samą funkcją (czyli Length(Tablica) zwróci wartość różną od 0), bo kolumna o indeksie 0 istnieje zawsze i nie ma możliwości usunąć jej;

cimak napisał(a)

napisz sobie osobna aplikacje testowa do obslugi array of array of string, a pozniej to przenies do swojego programu.

Tak też mam zamiar zrobić, ale dopiero jak się wyśpię; Deklaracja i definicja wszystkiego co jest zawarte w klasie zajmuje przeszło 2,5 tys. linii kodu stąd ciężko w dość krótkim czasie wykryć błąd szczególnie, jak siadam do komputera pod wieczór zmęczony po pracy...

Edit: Ilość kolumn jest zawsze taka sama dla każdego wiersza, czyli każdy wiersz posiada tą samą ilość kolumn; Jest metoda do usuwania kolumn, ale i tak wszystkie wiersze pomimo ich dodawania i usuwania zawsze posiadają tą samą ilość kolumn; Jak Excel :P


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 4x, ostatnio: flowCRANE
Azarien
  • Rejestracja:około 21 lat
  • Ostatnio:mniej niż minuta
0

rany boskie, trzymaj sobie tę ilość kolumn w osobnym polu klasy.

Misiekd
  • Rejestracja:około 21 lat
  • Ostatnio:ponad 12 lat
  • Postów:7923
2
Furious Programming napisał(a)

Chodzi o to, że tak jak wspomniałem w Excel'u jest możliwa taka sytuacja, że tabela jest pusta (czyli nie ma wierszy)
NIEPRAWDA!!!!! to, że "tabela" jest pusta oznacza tylko i wyłącznie tyle, że żadna komórka nie jest wypełniona! Możesz zrobić dokładnie tak samo - stworzyć wiersze SetLength(Tablica, IloscWierszy); a potem stworzyć w każdym wierszu pola for i := 0 to IloscWierszy - 1 do SetLength(Tablica[i], IloscKolumn) i pozostawić je puste, czyli nie przypisywać Tablica[wiersz, kolumna] := 'dupa'


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0
Azarien napisał(a)

rany boskie, trzymaj sobie tę ilość kolumn w osobnym polu klasy.

Owszem, mógłbym, ale musiałbym wtedy trzymać tak samo osiem innych ilości i indeksów w osobnych polach a to marnowanie pamięci, poza tym kdeklaracja klasy się wydłuży; Poza tym w każdej metodzie zmieniającej ilość wierszy czy kolumn musiałbym tą wartość zwiększać lub zmniejszać, a to strata czasu; Myślisz, że źle robię dbając o to, by klasa zajmowała jak najmniej w pamięci...?

Misiekd napisał(a)

NIEPRAWDA!!!!! to, że "tabela" jest pusta oznacza tylko i wyłącznie tyle, że żadna komórka nie jest wypełniona!

Zależy co kto rozumie pod pijęciem pusta; Dobrze piszesz, tabela jest pusta jak wszystkie komórki nie są wypełnione, ale nie o takie znaczenie słowa pusta mi chodzi; Excel to może niezbyt dobry przykład, bo w arkuszach kalkulacyjnych AFAIR nie usuwa się wierszy ani kolumn; W sumie nie ma do czego tego porównać, żeby to zobrazować;

Misiekd napisał(a)

Możesz zrobić dokładnie tak samo - stworzyć wiersze SetLength(Tablica, IloscWierszy); a potem stworzyć w każdym wierszu pola for i := 0 to IloscWierszy - 1 do SetLength(Tablica[i], IloscKolumn) i pozostawić je puste, czyli nie przypisywać Tablica[wiersz, kolumna] := 'dupa'

Jasne, że mogę i tak właśnie manipulowałem ilością wierszy i kolumn, ale zrezygnowałem z tego by przyspieszyć dodawanie wierszy i kolumn; To chyba też nie wada, że klasa będzie szybsza...?

Ok chłopaki, nie zagłębiajmy się dalej zagadnieniem kolejności indeksów, bo nie to jest przyczyną; Zrobiłem sobie osobny programik do testowania pod różnymi aspektami tablicy dwuwymiarowej przechowującej dane typu String i ku mojemu zaskoczeniu wszystko działa; Tworzyłem nawet o wiele większe tablice i nie było żadnego problemu ani z zapisem, ani odczytem informacji z poszczególnych komórek; Stąd jestem teraz w 100% pewny, że nie przyczyną jest kolejność indeksów;

Błąd odnalazłem w warunku sprawdzającym poprawność indeksów; Otóż np. w metodzie służącej do wpisywania nowej wartości w parametrze podaje się indeks kolumny, wiersza i nową wartość; Mniej więcej deklaracja wygląda tak:

Kopiuj
procedure WriteCell(iColumnIndex, iRowIndex: Integer; sValue: String);

Wszystko chyba jest dość sugestywne; Warunek sprawdzający poprawność obydwu indeksów sprawdza jednocześnie* czy indeks kolumny mieści się w odpowiednim przedziale, a po słowie and sprawdzany jest w ten sam sposób indeks wiersza, po czym całość jest negowana:

Kopiuj
if not ((iColumnIndex in [Low(PTable^) .. High(PTable^)]) and
        (iRowIndex in [Low(PTable^[0]) .. High(PTable^[0])])) then Exit;

Warunek dosyć prosty i wygodny, ale nie do końca prawidłowy, bo po jego rozbiciu na dwa osobno:

Kopiuj
if not iColumnIndex in [Low(PTable^) .. High(PTable^)] then Exit;
if not iRowIndex in [Low(PTable^[0]) .. High(PTable^[0])] then Exit;

wszystko działa bez zarzutu; Niestety dziwne to jest, bo klasę po napisaniu czy modyfikacji każdej metody dokładnie testuję, by wykluczyć ewentualne błędy; Wszystkie metody dodające, usuwające i wstawiające (czyli wszystkie te, które manipulują ilością kolumn i wierszy) testowałem na małej ilości kolumn i wierszy tak, by zawartość tablicy mieściła się w komponencie TListBox, bo w nim właśnie wyświetlałem wyniki działania metod; Liczba kolumn nie była większa niż 7, a wierszy niż 20; To mnie właśnie dziwi, że na małej ilości danych warunek sprawdzał się, a na większej już nie; Spędzałem dość dużo czasu na sprawdzenie poprawności działania metod, próbowałem wszystkich możliwości jakie dopuszcza i nie dopuszcza ten właśnie nie do końca poprawny warunek; Zwiększałem ilości o 1 i test, znów o jeden i test itd itd... wszelkie możliwe sposoby podania złych danych sprawdzałem i było wszystko ok; Dlatego właśnie nie podejrzewałem, że właśnie w ten sposób skonstruowany warunek może przynieść takie błędy...

Czyli już po kłopocie; Mam jeszcze jedno pytanie: czy ktoś wie dlaczego ten pierwszy warunek takie jaja odstawia? Co należy w nim zmienić, by był poprawny w każdej sytuacji? Dziękuję serdecznie za zainteresowanie i pomoc;

*jednocześnie - w znaczeniu w jednej instrukcji warunkowej if;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
0

W pierwszym przypadku oba warunki muszą być spełnione, potem jest robiona negacja. W drugim przypadku wystarczy jeden spełniony warunek, aby zrobić Exit - więc tak na szybko: and -> or dla jednego zapytania?
...

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Tuchów
  • Postów:12126
0

Muszą być spełnione oba warunki, bo indeksy muszą się mieścić zarówno w przedziale wierszy jak i kolumn, dlatego właśnie tak skonstruowałem warunek; W sumie też mogło by być tak:

Kopiuj
if (not iColumns in [Low(PTable^) .. High(PTable^)]) or
   (not iRowIndex in [Low(PTable^[0]) .. High(PTable^[0])]) then Exit;

W sumie tak, jeżeli choć jeden z indeksów nie mieści się w przedziale procedura zostanie zamknięta; A czy to będzie działać to muszę sprawdzić, bo już raz się pomyliłem;

Dziękuję wszystkim za zainteresowanie tematem i pomoc, przepraszam jeśli kogoś wyprowadziłem z równowagi; Pozdrawiam;


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)