>Czy ktos wie jak zmusic clippera aby w przypadku wystapienia zmiennej
>prywatnej i pola bazy danych o identycznej nazwie - bral najpierw wartosc ze
>zmiennej a nie z pola bazy ?
>Mam ten zwyczaj, ze odwolania do pol zawsze poprzedzam odwolaniem
>FIELD->nazwaPola.
Ja zawsze uzywam alias->nazwapola gdzie 'alias' to alias bazy podany
przy otwarciu (najczesciej dwuliterowy). FIELD uzywam tylko wtedy gdy wiem
ze dana procedura moze byc wolana dla kilku baz majacych pola z tymi
samymi nazwami. Choc ostatnio wole alias bazy przekazywac jako parametr i
uzyc (cAlias)->nazwapola.
>Ostatnio dolozylem jakies pole ktore sie pokrylo z nazwa zmiennej - i szereg
>programow przestal dzialac. Stracilem kupe czasu na takim głupim przypadku.
>Moze jest jakis SET(...) albo przelacznik kompilacji ? Zmienne musza byc
>niestety prywatne, a niechce mi sie ich poprzedzac odwolaniem
>M->id_Zmienna.
M->zmienna u mnie musi byc obowiazkowo. Zawsze kompiluje z parametrem -w
Najnowsza praktyka (u mnie) to dodawanie do nazwy literki 'v' dla
zmiennych PRIVATE i literki 'u' dla zmiennych PUBLIC -choc staram sie
unikac takich zmiennych.
Jesli chcesz aby wszystkie zmienne (oczywiscie poza LOCAL) byly brane jako
MEMVAR to przy kompilacji musisz uzyc parametru -a =Automatic memvar
declaration lub parametru -v = Variables are assumed M->
Pozdrawiam, Ryszard
PS. Opis parametrow kompilacji mozna uzyskac po wywolaniu kompilatora bez
podawania nazwy zbiorudo kompilacji :)
--
r(ycho)GLAB
Warsaw, Poland
http://www.waw.pdi.net/~rglab
Tak, ale to nie dziala z blokow kodu. U mnie EXE zna nazwy tylko 9 baz
danych, a obsluguje ponad 80. Cala reszta informacji jest pobierana z plikow
zewnetrznych i zamieniana na bloki kodu. Alias->pole dziala bez zarzutu, ale
( zmiennaCoZnaAlias)->Pole nie przechodzi prze kompilacje do bloku kodu.
>Jesli chcesz aby wszystkie zmienne (oczywiscie poza LOCAL) byly brane jako
>MEMVAR to przy kompilacji musisz uzyc parametru -a =Automatic memvar
>declaration lub parametru -v = Variables are assumed M->
(-v) jest parametrem kompilacji. Mi chodzi o czas wykonania. Zmienne
istotne w swoim znaczeniu maja nazwy kojarzace je ze swoim przeznaczeniem.
Ale sa i rozne liczniki i zmienne fragmentow ekranu. Mialem wlasnie taka
zmienna - e := Okno( 'Jakis napis'). Okno to wyswietlilo, i zwrocilo
fragment ekranu do zmiennej e. Klient chcial 5 nowych rodzajow cen,
Dolozylem pola od A do E,
No i jak odtwarzany byl ekran [ RestBox( e)] - to RestBox() zamiast zmiennej
dostal wartosc pola numerycznego. Wyjsciem bylobu RestBox( M->e) - ale
wolalem zmienic nazwy pol na CENA_A .... CENA_E. Wszystko to dzieje sie w
czasie wykonania, a EXE nie jest zmieniane, tylko nazwijmy to "skrypty".
Wygodniej jest poprzedzac pola aliasami lub znacznikami FIELD->, gdyz jest
ich po prostu mniej w programach, a i odwolania sa jakby gatunkowo ciezsze.
Clipper natomiast, co mu zostalo po DBASE, w opisanym przypadku bieze
wartosc pola przed wartoscia zmiennej. To jest wg mnie niezreczne
rozwiazanie, i myslalem ze mozna to jakos zmienic.
Pozdrawiam, Marek Horodyski
[ciachnięcie...]
1. Dobrą praktyką jest (nie ja to wymyśliłem :) oznaczanie zmiennych za
pomocą odpowiednich liter np:
a - Array, c - Character, n - Number, o - Object, itd...
dzięki temu kod źródłowy jest bardziej przejrzysty:
local cFile, nFile
local aFile := directory('*.txt')
for nFile := 1 to len(aFile)
cFile := aFile[nFile,1]
? cFile
next nFile
Istnieje wprawdzie ryzyko, że nazwa jakiejś zmiennej z przedrostkiem pokryje
się z nazwą pola w bazie danych, ale to już inna sprawa.
2. Zmienne definiowane po słowach PUBLIC, PRIVATE i PARAMETERS (i nie
deklarowane) są przechowywane w pamięci dynamicznej. Pamięć ta jest powolna
(swap) i błędogenna (fragmentacja pamięci i niejednoznaczności). Dużo lepiej
jest trzymać wszystko w zmiennych lokalnych i statycznych. Są zapisywane w
pamięci statycznej i są wiązane na krótko (przez adres, a nie nazwę).
Zmienne takie są szybsze, powodują mniej błędów i nie rozdmuchują tablicy
symboli. A że nie są obsługiwane przez makra ? Można się bez tego obejść.
3. Nazywanie zmiennych jedną literką (nieśmiertelne "for i := 0 to 255")
jest bardzo złym przyzwyczajeniem. Sam musiałem długo z tym walczyć. Ale
opłaciło się. Gorącą polecam nieco dłuższe nazwy.
PS. Przepraszam jeśli pisałem rzeczy dla wszystkich oczywiste :) Dodam
jeszcze, że parę lat temu podzieliłem swoje systemy na małe funkcjonalne
moduły (obsługa drukarki, obsługa użytkowników, obsługa ustrojstw
fiskalnych, itd.), w każdym zawarłem wszystkie funkcje i procedury z nimi
związane. Wszystkie zmienne podzieliłem na lokalne (widoczne w obrębie
procedury) i statyczne (widoczne w obrębie modułu). Wyeliminowałem omal
wszystkie przekazania parametrów i wyników (przekazywanie parametrów w
Clipper'ze jest bardzo powolne) - zastępują mi je zmienne statyczne.
Większość funkcji i procedur zrobiłem statycznymi (widoczne tylko w obrębie
modułu). Zmiennych niezadeklarowanych, PRIVATE i PARAMETERS nie mam w ogóle.
Zmiennych publicznych zostało mi jeszcze parę, ale to tylko kwestia czasu. W
efekcie uzyskałem znaczne przyspieszenie programów i o niebo większą
przejrzystość źródeł. Że nie wspomnę o tym że moduły mogę sobie wymieniać
pomiędzy aplikacjami jak karty w PeCecie i wszystko gra. Jeszcze raz
przepraszam za nudziarstwo :)
Swieta prawda. Tak tez i ja mam. Tylkoże u mnie EXE ma tylko kilkaset
malutkich objotow, ktore sluza do uruchamiania zewnetrznych programow. Takie
DBASE, albo FOXBASE. I uruchamiajac te zewnetrzne programy tworzone sa na
ich potrzeby zmienne prywatne. Dostep do nich jest rownie szybki (testowalem
to - niech pisza co chca w dokumentacji, mi wychodzilo to samo), problemem
moze byc tylko tablica symboli. Ale w 5.3 nie ma juz zadnych problemow.
>zmiennych, PRIVATE i PARAMETERS nie mam w ogóle.
>Zmiennych publicznych zostało mi jeszcze parę, ale to tylko kwestia czasu.
To tak samo jak ja. Zostaly mi dwie zmienne publiczne, ktore beda musialy
zostac.
Ale dostep do nich chce zrobic poprzez obiekty - i dlatego szukalem
biblioteki obiektowej, ktora juz sciagnolem. Zmienne prywatne sa generowane
w celach informacyjnych dla uruchamianych procesow - taki protokol wymiany
informacji. Procesy potomne moga jednak tworzyc tylko zmienne prywatne. EXE
nawet nie wie, czy obsluguje hotel, czy biuro matrymonialne - wazne aby
uzytkownik byl zadowolony.
Pozdrawiam - Marek Horodyski
Niezbyt dokładnie się wyraziłem. Powolność zmiennych PRIVATE i PUBLIC wynika
z dwu przyczyn:
1. Muszą być znalezione w tablicy symboli - odpada jeśli tablica mała.
2. Muszą być swapowane jeśli mało pamięci - odpada jeśli EXE niewielki.
Jak zwykle wszystko zależy od niuansów. Natomiast przekazywanie parametrów
do i od funkcji i procedur przetestowałem dokładnie. Spowalniają jak
cholera. Ale to już nie na temat :)
[...]
>Tak, ale to nie dziala z blokow kodu. U mnie EXE zna nazwy tylko 9 baz
>danych, a obsluguje ponad 80. Cala reszta informacji jest pobierana z plikow
>zewnetrznych i zamieniana na bloki kodu. Alias->pole dziala bez zarzutu, ale
>( zmiennaCoZnaAlias)->Pole nie przechodzi prze kompilacje do bloku kodu.
To akurat daje sie prosto ominac. Zamiast
PRIVATE vcAlias
M->vcAlias :='baza'
bBlock :=&( '{|| (vcAlias)->pole}' )
nalezy uzyc
bBlock :=&( '{|| &vcAlias->pole}' )
lub
bBlock :=&( '{|| &vcAlias.->pole}' )
[...]
>Wygodniej jest poprzedzac pola aliasami lub znacznikami FIELD->, gdyz jest
>ich po prostu mniej w programach, a i odwolania sa jakby gatunkowo ciezsze.
>Clipper natomiast, co mu zostalo po DBASE, w opisanym przypadku bieze
>wartosc pola przed wartoscia zmiennej. To jest wg mnie niezreczne
>rozwiazanie, i myslalem ze mozna to jakos zmienic.
W takim razie pozostaje tylko rozbudowanie Twojego kompilatora skryptow
o mozliwosc automatycznego dodawania 'M->' lub 'FIELD->' przed kazda
zmienna ktora nie ma operatora '->'. Maly drobiazg na wieeeele dni
pracy ;)
Pozdrawiam, Ryszard
[...]
>2. Zmienne definiowane po słowach PUBLIC, PRIVATE i PARAMETERS (i nie
>deklarowane) są przechowywane w pamięci dynamicznej. Pamięć ta jest powolna
>(swap) i błędogenna (fragmentacja pamięci i niejednoznaczności). Dużo lepiej
>jest trzymać wszystko w zmiennych lokalnych i statycznych. Są zapisywane w
>pamięci statycznej i są wiązane na krótko (przez adres, a nie nazwę).
Co do zmiennych lokalnych to zgoda ale ze statycznymi nalezy byc
ostroznym. Zmienne te sa alokowane w segmencie DGROUP gdzie ponadto
znajduje sie stos procesora, stos ze zmiennymi roboczymi, lokalnymi
i parametrami funkcji/procedur (eval stack) oraz wszelkie dane zaalokowane
w modulach w C/ASM. Jesli przesadzimy z iloscia zmiennych statycznych to
moze sie zdarzyc ze w eval stack zabraknie miejsca na przechowanie
wartosci zmiennych lokalnych i parametrow funkcji - mamy wtedy eval stack
fault 667. Dodatkowo jesli jest malo wolnej pamieci to zarzadca pamiecia
wirtualna (VMM) rowniez pobiera sobie pamiec z segmentu DGROUP.
Jesli dodatkowo ktos zamiast zmiennej publicznej utworzy zmienna
statyczna i do jej obslugi utworzy mnostwo funkcji ktorych nazwy wchodza
do tablicy symboli to wykorzystanie pamieci jest jeszcze gorsze.
Oczywiscie tak jest latwiej panowac nad kodem programu ale trzeba zdawac
sobie sprawe z tego ze jest to jakims kosztem.
Poza tym nie rozumiem co znaczy ze pamiec jest 'bledogenna' -
fragmentacja pamieci bedzie zarowno wtedy gdy stosuje sie zmienne prywatne
jak i lokalne - jesli wartoscia zmiennej jest string, tablica lub blok
kodu to w obu przypadkach jest alokowana pamiec z puli VMM.
Rowniez odwolania do zmiennych prywatnych i publicznych nie sa przez
nazwe ale przed odwolanie do konkretnego symbolu w tablicy symboli.
Tablica ta jest przeszukiwana tylko podczas kompilacji makra lub
w momencie napotkania niezadeklarowanej zmiennej.
>Zmienne takie są szybsze, powodują mniej błędów i nie rozdmuchują tablicy
>symboli. A że nie są obsługiwane przez makra ? Można się bez tego obejść.
>3. Nazywanie zmiennych jedną literką (nieśmiertelne "for i := 0 to 255")
>jest bardzo złym przyzwyczajeniem. Sam musiałem długo z tym walczyć. Ale
>opłaciło się. Gorącą polecam nieco dłuższe nazwy.
Nie bardzo widze sensu aby zmienna w petli FOR nazywac inaczej niz i,j,k
jesli tylko beda uzywane do tego celu konsekwentnie (poza tym moim
pierwszym jezykiem byl FORTRAN :). Jesli petla ma sie wykonac 200 razy
to bardzo trudno bedzie znalezc jakas logiczna nazwe dla tej zmiennej.
Jedynie w przypadkach operacji na wielowymiarowych tablicach stosuje nazwy
ktore odpowiadaja zawartosciom. W innych przypadkach uzywanie
jednoliterowych nazw jest rzeczywiscie proszeniem sie o klopoty.
[...]
>procedury) i statyczne (widoczne w obrębie modułu). Wyeliminowałem omal
>wszystkie przekazania parametrów i wyników (przekazywanie parametrów w
>Clipper'ze jest bardzo powolne) - zastępują mi je zmienne statyczne.
Czyli emulujesz zmienne publizne za pomoca statycznych. Przekazywanie
parametrow polega na przekopiowaniu 14 bajtow w eval stack na kazdy
parametr i pozniej 14 bajtow dla wartosci zwracanej. Co moze byc tutaj
wolnego? Mysle ze zysk na predkosci nie uzasadnia takiego postepowania.
[...]
>efekcie uzyskałem znaczne przyspieszenie programów i o niebo większą
>przejrzystość źródeł. Że nie wspomnę o tym że moduły mogę sobie wymieniać
Nie wierze w to ze uzywanie zmiennych statycznych do przekazywania
parametrow daje wieksza przejrzystosc - w kazdym badz razie nie dla mnie.
>pomiędzy aplikacjami jak karty w PeCecie i wszystko gra. Jeszcze raz
>przepraszam za nudziarstwo :)
Testowalem to, i to jednak nie przechodzi przez kompilacje. To by przeszlo,
gdyby tekst tworzacy blok kodu byl widoczny w czasie kompilacji. Wtedy makro
jest rozwijane jak w przypadku :
Local imie
imie := 'Jacek'
? 'Czesc &imie . Jak sie masz?'
Ale gdy tekst dostaje sie w czasie wykonania, to nie moze byc w nim makra.
Otrzyma sie blad kompilacji. Dawno to juz testowalem, a dzisiaj powtorzylem.
Troche szkoda, bo gdyby clipper to robil i z tak otrzymanego tekstu to mozna
by znacznie uelastycznic programy. To cos jak z FieldBlock() i
FieldWBlock().
> W takim razie pozostaje tylko rozbudowanie Twojego kompilatora skryptow
>o mozliwosc automatycznego dodawania 'M->' lub 'FIELD->' przed kazda
>zmienna ktora nie ma operatora '->'. Maly drobiazg na wieeeele dni
>pracy ;)
Myslalem o tym, ale to jest i trudne, a skorka za wyprawke sie moze nie
oplacic. Najprawdopodobniej spowolnilo by to znacznie czas kompilacji -
musialbym napisac analizator skladni wyrazenia, ktory musialby trwac. Zalezy
mi na jak najszybszej kompilacji. Na K5 program ktory ma 720 linii kompiluje
sie ok. 2s, a zaczynalem z tym programem od 35s na 386DX40. W jakiejs
ksiazce wyczytalem ze AADD() przy wiekszych tablicach dosc dlugo trwa.
Poszczegolne instrukcje kompiluje do blokow kodu i dodaje je wlasnie AADD()
do tworzonego stosu programu. Bardzo wyraznie na wolniejszych komputerach
bylo widac spowolnienie powyzej 300 elementow tablicy. Myslalem ze to
AADD(). Ale gdzie tam. Program pobieralem Memoreadem(), a poszczegolne linie
wyciagalem MemoLine'm() - ktory to wlasnie tak dlugo trwal (i coraz dluzej w
miare przyrostu wielkosci pliku). Przypadkowo sprobowalem przetestowac
jakies funkcje z toolsow i zobaczylem przyczyne. Teraz zrobilem point do
zmiennej tekstowej programu, i wydlubuje linie SubStr'ingiem(). Dziala to
teraz na tyle szybko, ze jestem mocno zadowolony. Najwyzej raz do roku bede
mial stan przedzawalowy, jak mi wyjdzie jakis blad z niewiadomych przyczyn
:-)
Pozdrawiam, Marek Horodyski
Witajcie,
sprawdzilem i dziala :
bBlock :=&( '{|| ' + vcAlias + '->pole}' )
Pozdrawiam,
Marek Powichrowski
Bo to nie o to chodzi. Dziala to np. tak :
bBlock :=&( '{|| Pozycje->Towar}' )
ale nie dziala :
Local lub Private zmienna := 'Pozycje'
bBlock :=&( '{|| (zmienna)->Towar}' )
co mozna uzyskac pod czystym clipperem.
Nie moge tez uzyskac :
bBlock :=&( '{|| &Zmienna->Towar}' )
gdy tekst w uszach nie jest widoczny w czasie kompilacji do OBJ, a co byloby
dobrym obejsciem problemu.
Marek Horodyski
>>nalezy uzyc
>>bBlock :=&( '{|| &vcAlias->pole}' )
>>lub
>>bBlock :=&( '{|| &vcAlias.->pole}' )
>>
>
>Testowalem to, i to jednak nie przechodzi przez kompilacje. To by przeszlo,
>gdyby tekst tworzacy blok kodu byl widoczny w czasie kompilacji. Wtedy makro
>jest rozwijane jak w przypadku :
[...]
Przepraszam wyrazilem sie niejasno. To byl tylko schemat. Poniewaz
faktycznie kompilator makr nie potrafi obsluzyc az tak skomplikowanego
wyrazenia to nalezy zdefiniowac ponizsza funkcje w 'prawdziwym' kodzie
programu:
FUNCTION ScriptMacro( cMacro )
RETURN( &( cMacro ) )
i teraz juz mozesz szalec z makrami dowolnie. Powyzszy kod w skrypcie
bedzie wiec wygladal:
bBlock:=ScriptMacro( '{|| &vcAlias->pole}' )
EVAL( bBlock )
[...]
>Myslalem o tym, ale to jest i trudne, a skorka za wyprawke sie moze nie
>oplacic. Najprawdopodobniej spowolnilo by to znacznie czas kompilacji -
>musialbym napisac analizator skladni wyrazenia, ktory musialby trwac.
To byl tylko zart...
> Zalezy
>mi na jak najszybszej kompilacji. Na K5 program ktory ma 720 linii kompiluje
>sie ok. 2s, a zaczynalem z tym programem od 35s na 386DX40. W jakiejs
>ksiazce wyczytalem ze AADD() przy wiekszych tablicach dosc dlugo trwa.
Zgadza sie. Wszystkie elementy tablicy musza byc umieszczone w pamieci
w jednym kawalku. Tyle ze kazdy element tej tablicy zawiera wewnetrzna
strukture Clippera o nazwie VALUE ktora sluzy do przechowywania wartosci
zmiennej (jesli jest to integer lub string krotszy niz 4 bajty) lub
wskaznika do miejsca w pamieci gdzie jest przechowywana wlasciwa wartosc
(np. duzy string lub nastepna tablica). Struktura ta zajmuje 14 bajtow
(stad ograniczenie na maksimum 4096 elementow w tablicy). Teraz w momencie
uzycia funkcji AADD() Clipper alokuje nowy kawalek pamieci tyle ze ten
nowy kawalek ma o jeden element wiecej. Nastepnie po prostu kopiuje
zawartosc starego kawalka pamieci i na koniec kopiuje strukture VALUE dla
dodawanej wartosci. Stad im wieksza tablica to tym wiecej kopiuje bajtow
i wiecej wahluje pamiecia wirtualna. Dlatego zawsze lepiej jest od razu
deklarowac wielkosc tablicy (oczywiscie jesli tylko mozna to z gory
okreslic).
Czyli zamiast:
aArr :={}
GOTO TOP
DO WHILE( !EOF() )
AADD( aArr, FIELD->pole )
SKIP
ENDDO
mozna uzyc
aArr :=ARRAY( LASTREC() )
GOTO TOP
FOR i:=1 TO LASTREC()
aArr[i] :=FIELD->pole
SKIP
NEXT
>Poszczegolne instrukcje kompiluje do blokow kodu i dodaje je wlasnie AADD()
>do tworzonego stosu programu. Bardzo wyraznie na wolniejszych komputerach
>bylo widac spowolnienie powyzej 300 elementow tablicy. Myslalem ze to
>AADD(). Ale gdzie tam. Program pobieralem Memoreadem(), a poszczegolne linie
>wyciagalem MemoLine'm() - ktory to wlasnie tak dlugo trwal (i coraz dluzej w
>miare przyrostu wielkosci pliku). Przypadkowo sprobowalem przetestowac
>jakies funkcje z toolsow i zobaczylem przyczyne. Teraz zrobilem point do
>zmiennej tekstowej programu, i wydlubuje linie SubStr'ingiem(). Dziala to
>teraz na tyle szybko, ze jestem mocno zadowolony. Najwyzej raz do roku bede
>mial stan przedzawalowy, jak mi wyjdzie jakis blad z niewiadomych przyczyn
Na Oasis jest zbior buffread.zip ktory podobno 'dramatically improve
performance' przez buforowanie odczytanego tekstu. Funkcja ta zwraca po
jednej linii tekstu.
> Zgadza sie. Wszystkie elementy tablicy musza byc umieszczone w pamieci
>w jednym kawalku. Tyle ze kazdy element tej tablicy zawiera wewnetrzna
>strukture Clippera o nazwie VALUE ktora sluzy do przechowywania wartosci
>zmiennej (jesli jest to integer lub string krotszy niz 4 bajty) lub
[...]
>deklarowac wielkosc tablicy (oczywiscie jesli tylko mozna to z gory
>okreslic).
Myslalem o segmentowaniu. Np. co 100 elementow. A na koncu jedno obciecie do
uzasadnionego rozmiaru. Ale to rozwiazanie bylo by lepsze dla duzych
programow, u mnie natomiast jest bardzo duzo malych programow, i na koncu
moze sie okazac, ze impreza sie nie oplacala. Do lutego br. trzymalem teksty
w polach znakowych. Jak bylo potrzeba - byly tam wywolania programow z
plikow zewnetrznych. Tych plikow narobilo sie tak duzo, ze trudno mi bylo
nad tym zapanowac, i musialem cos zmienic.Teraz przeszedlem na pola memo. To
znakomicie uelastycznia wygde sterowania, ale i zauwazalnie wydluza czas
jego wczytywania . Na baze faktur z pozycjami jest ca 350 czytan
przeplatanych kompilacja. To jest wlasnie przyklad niespodziewanego efektu
ubocznego. Powrot do poprzedniej wersji jest praktycznie niemozliwy
(zdarzalo sie juz ze machalem reka na 3 m-ce pracy, bo efekt byl niedobry).
Teraz to juz chyba tylko nadzieja na postep w coraz szybszych procesorach.
......
Musze wypluc to co wyzej napisalem. Zmierzylem czasy. W poprzedniej wersji
(a byl to clipper 5.2) Otwarcie danych z kompilacja trwalo 4 s, po
kompilacji 1s. W nowej wersji (pod clipperem 5.3 i z polami memo) otwarcie
trwalo odpowiednio 3s i 1s. W nowej wersji wiecej sie wyswietla. Kazde pole
ma kilka parametrow, w tym 2 programy, plus 14 programow na dokument ( w
przypadku dokumentow z pozycjami * 2), plus firmy, plus magazyny. Przedtem
nie bylo to wyswietlane, a teraz pojawiaja sie napisy kompilowanych
programow, np FAKTURY->Firma.START, FAKTURY->Firma.VALID ... Gdy sie takich
napisow pokaze kilkaset w ciagu 2s, to subiektywnie odnosi sie
przytlaczajace wrazenie wydluzenia czasu wczytywania. Obiektywnie jednak
clipper 5.3 jest znacznie szybszy od 5.2, nawet gdy czyta sie z pol memo.
Sprawdzone w praktyce.
> Na Oasis jest zbior buffread.zip ktory podobno 'dramatically improve
>performance' przez buforowanie odczytanego tekstu. Funkcja ta zwraca po
>jednej linii tekstu.
Te w toolsach tez sa bardzo szybkie. W przypadku b. duzych zmiennych
tekstowych czas ten jest kilkadziesiat razy krotszy. Ale tam jest najpierw
wywolanie kontrolne i wstawienie czegos na ksztal tagow. Rozwiazanie z
substringami moze jest od tego jakies 10 % wolniejsze, ale nie dolacza sie
kolejnych funkcji, co tez nie jest bez znaczenia.
Pozdrawiam, Marek Horodyski