Strona: [  << <   1   > >>  ]  z  1     
Autor Temat: Scalanie tablic
mikmas
From Łódź Stadt




Typ: neutral
Postów: 772
Zarejestrowany: Apr 2003
Scalanie tablic

Napisałem sobie funkcję:

Function Scal(SourceArray() As String) As String
    Dim Lenght As Long
    For I = 0 To UBound(SourceArray)
        Lenght = Lenght + Len(Trim(Str(SourceArray(I))))
    Next
    Scal = String(Lenght, Chr(0))
    CopyMemory ByVal StrPtr(Scal), ByVal StrPtr(SourceArray(0)), Lenght
End Function


No i małe bzdurki pisze:
"0doject1dd?d?gP??d?g???????ddddddddddd?ddd__SRP_dd??e?g?cd?g?d20d`Äd ?d21ddddddd?gD?8dCdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
d to chr(0), tylko na forum nie wyświetla, to zamieniłem . Może źle wywnioskowałem, ale StrPtr zwraca pozycję zmiennej w pamięci? Jeśli tak, to - co dziwne - dla tablicy (bo myślałem, że tu jest błąd) nie podaje wartości, która by wszystko wyjaśniała - 0, tylko jakąś 6 770 600, co jest - myślę - dość realną liczbą, a więc: co jest źle?


_____________________________________________
4C;65;70;69;65;6A;20;62;79;9C;20;73;69;EA;20;
62;61;72;64;7A;69;65;6A;20;73;6B;6F;6E;63;65;
6E;74;72;6F;77;61;B3;20;6E;61;20;6F;64;70;6F;
77;69;65;64;7A;69;2C;20;61;20;6E;69;65;20;6E;
61;20;72;6F;7A;73;7A;79;66;72;6F;77;79;77;61;
6E;69;75;20;3A;50

12-05-2005 18:31
Pokaż profil mikmas  Wyślij email do mikmas   Odwiedź stronę mikmas       3632553
marcin_an
Forumowicz




Typ: neutral
Postów: 1265
Zarejestrowany: Mar 2004

1)
Lenght = Lenght + Len(Trim(Str(SourceArray(I))))
A po co zamiana Stringu na String?

2)
Postaram się to wytłumaczyć najprościej, jak potrafię (w razie czego służe pomocą na GG).

Zacznijmy od tego, czym jest String w pamięci, bo bez tego nie ma sensu wogóle próbować ich kopiować. To, co nazywamy Stringiem to w rzeczywistości typ BSTR. Składa się on z trzech elementów. Pierwszy z nich to 32-bitowy wskaźnik. Zmienne, do których mamy dostęp, to właśnie te wskaźniki. Drugim elementem jest sam łańcuch znaków zapisanych jako UNICODE i zakończonych NUL (0000). Wspomniany wcześniej wskaźnik pokazuje na początek tego ciągu. Trzecim elementem jest pole długości ciągu zaczynajace się 4 bajty przed początkiem ciągu znaków.

Graficznie można przedstawić to tak:


    WSKAŹNIK--.
              |
              |
              V
  LL LL LL LL AB CD EF GH JK ... 00 00


Teraz przejdźmy do tablic. Nie będe się tutaj zagłębiał w to, jak zbudowany jest typ SafeArray, powiem tylko tyle, że tablica elementów typu String to z punktu widzenia komputera tablica wskaźników opisanych wcześniej. Co za tym idzie - w rzeczywistości kolejne Stringi nie są poukładane jeden za drugim w tablicy, lecz mogą być "porozrzucane" po pamięci - jedynie wskaźniki do nich są "ułożone".

Przechodząc do samego kodu:
Funkcja StrPtr zwraca adres początku ciągu znaków, w przeciwieństwie do VarPtr, która w tym przypadku zwróciłaby adres wskaźnika do początku ciągu znaków. W momencie, gdy próbowałeś skopiować wszystkie ciagi procedurą CopyMemory, naprawdę podałeś jej jedynie adres pierwszego z nich. Skopiowałeś zatem tylko pierwszy, a resztę zmiennej wypełniły przypadkowe dane z pamięci. Podczas kopiowania musisz poprostu skopiować każdy element tablicy oddzielnie.

I dwie kolejne sprawy:
1) Do pobrania długości danych użyłeś funkcji Len, któa w przypadku zmiennych typu String zwróci ilość znaków, nie długość w bajtach. Ponieważ znaki są zapisane jako Unicode - każdy z nich zajmuje 2 bajty i tym samym - przygotowałeś o połowę za mało miejsca. Musisz albo użyć LenB, albo pomnożyć wynik Len przez 2.
2) Użyłeś funkcji Trim. Zauważ, że w takiej formie, w jakiej go uzyłeś, zapis:
Len(Trim(jakisstring)) zwróci ci długość ciagu znaków bez kkończowych i początkowych spacji, podczas, gdy w pamięci te SPACJE NADAL TAM BĘDĄ. Podam przykład:
Niech bedzie sobie ciag znaków:

"  ala ma kota"
Długość = 13 znaków
Len(Trim("  ala ma kota" )) zwróci jednak tylko 11
Przy kopiowaniu zostanie wtedy skopiowane tylko 11 pierwszych znaków... ale przecież te dwie pierwsze spacje nadal tam będą i nastąpi skopiowanie jedynie:
"  ala ma ko"


No to tyle. Jeśli coś gdzieś przekręciłem, proszę o zgłoszenie . W którejś wersji VB przechowywane były nie dane typu BSTR, ale wskaźniki do typu BSTR - czyli wskaxniki do wskaźników do ciagu znaków. Wydaje mi sie, zę to dotyczyło wersji 3, a nie 6.. ale jesli się mylę, też proszę o poprawienie mnie.


_____________________________________________
Jedzonko dla Google'a:
Forum na temat Visual Basic, C, C++, Pascal, Programowanie, API, PHP, VBA, VB.NET, QBasic, VBScript, Komputery
Moja strona o wszystkim

12-05-2005 22:00
Pokaż profil marcin_an  Wyślij email do marcin_an   Odwiedź stronę marcin_an  
karolinavb




Typ: neutral
Postów: 468
Zarejestrowany: Jan 2003

A skoro już jesteśmy przy temacie stringów i zmiennych, zbiorczo :

http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/ - How Visual Basic 6 Stores Data

Może też warto przeczytać dość istotną informację o przekazywaniu stringów do DLL :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/html/vbconpassingstringstodllprocedure.asp

Różnice między wersjami VB (przy okazji API) tutaj:

http://www.oreilly.de/catalog/win32api/chapter/
( lub http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnw32dev/html/ora_apiprog6_topic1.asp)

w skrócie tutaj:

http://www.romanpress.com/Articles/Strings_R/Strings.htm

[Post edytowany dnia 13-05-2005 06:35 przez karolinavb]


_____________________________________________
Karolina

13-05-2005 06:34
Pokaż profil karolinavb  Wyślij email do karolinavb   
Wszystkich odpowiedzi: 2 :: Maxymalnie na stronę: 20
Strona: [  << <   1   > >>  ]  z  1