Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Power Basic

Страница: 1 | 2 | 3 |

 

  Вопрос: Копия строки ? Добавлено: 22.12.08 22:17  

Автор вопроса:  Lapex
Доброе время суток!

Имеется функция, на вход которой передается указатель на строку ASCIIZ. Функция должна произвести манипуляции со строкой и вернуть указатель на измененную строку, при этом оригинальная строка не должна измениться.

Я так понимаю, чтобы не портить оригинальную строку - мне нужно создать копию строки и работать с этой копией, но к сожалению я не доконца понимаю механизм создания копии строки в памяти.
FUNCTION MyFunc (BYVAL lpSource AS ASCIIZ PTR) AS LONG

  LOCAL lpDest AS ASCIIZ PTR
  LOCAL nLen AS LONG

  nLen = LEN(@lpSource) + 1
  CopyMemory BYVAL lpDest,  BYVAL lpSource, BYVAL nLen ' ???
...

Этот код вызывает ошибку: "Память не может быть Writetten".

Возможно моя идея изначально не верна, пожалуйста подскажите, что нужно для моего случая.

Ответить

  Ответы Всего ответов: 37  

Номер ответа: 1
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #1 Добавлено: 22.12.08 23:14
Идея верна, только память в байтах выделить надо.
  1. FUNCTION MyFunc (BYVAL lpSource AS ASCIIZ PTR) AS  STRING
  2.  
  3.   LOCAL lpDest AS ASCIIZ PTR
  4.   LOCAL b() AS BYTE
  5.   LOCAL nLen AS LONG
  6.   nLen = LEN(@lpSource) + 1
  7.   REDIM b (nLen)
  8.   lpDest= VARPTR(b(0))
  9.   CopyMemory lpDest,  BYVAL lpSource, BYVAL nLen
  10.   MyFunc = @lpDest
  11. END FUNCTION
  12.  
  13. FUNCTION PBMAIN () AS LONG
  14.           LOCAL s AS STRING
  15.           LOCAL d AS STRING
  16.           s = "qwerty"
  17.           d  =  MyFunc(STRPTR(s))
  18. END FUNCTION

Ответить

Номер ответа: 2
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #2 Добавлено: 22.12.08 23:33
Спасибо огромное! То, что нужно!

Ответить

Номер ответа: 3
Автор ответа:
 alex



Вопросов: 84
Ответов: 453
 Профиль | | #3 Добавлено: 23.12.08 12:56
CopyMemory - очень медленная API функция. Для копирования строк лучше использовать операторы PEEK и POKE, они сразу компилируюся в ассемблерные инструкции и работают намного быстрее.

Ответить

Номер ответа: 4
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #4 Добавлено: 23.12.08 15:52
Спасибо!

Заменил:
  1. CopyMemory lpDest,BYVAL lpSource, BYVAL nLen

на:
  1. POKE$ lpDest, PEEK$(lpSource, nLen)

Работает!

Ответить

Номер ответа: 5
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #5 Добавлено: 25.12.08 09:52
У меня еще один вопрос, по копированию строки в памяти.

При копировании ASCIIZ-строк большой длины (больше 32Мб)- копия строки обрезается до 32Мб (33554432 байт), что это за магическое число, размер страницы памяти? и возможно ли перепрыгнуть этот барьер или лучше этого не делать?

Ответить

Номер ответа: 6
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #6 Добавлено: 25.12.08 12:26
Мда, поторопился я, скорее всего дело не в процессе копирования строки. Оказывается, что в переданном в функцию указателе - строка уже имеет обрезанный размер?! :(

Ответить

Номер ответа: 7
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #7 Добавлено: 25.12.08 14:22
Вообщем я понял, что ограничение на длину строки наложил тип ASCIIZ (max=33554432 байт), получается, если в параметре передан указатель на строку c размером выше 32Mb - я никак не смогу обработать эту строку?

Ответить

Номер ответа: 8
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #8 Добавлено: 25.12.08 14:54
Инструкция по эксплуатции PB:
LOCAL ASCIIZ строки создаются в стеке, таким образом LOCAL ASCIIZ будут ограничены доступного размером стека. Обычно это - менее чем 1 MB если размер стека не переопределен #STACK. Если требуются ASCIIZ строки боьшей длины желательно обьявить их INSTANCE, STATIC или GLOBAL.
STATIC и GLOBAL строки ASCIIZ могут быть вплоть до 16,777,216 байтов.

Хочешь больше - просто объявляй массив байт.

Ответить

Номер ответа: 9
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #9 Добавлено: 25.12.08 16:37
Мне очень стыдно, но что-то я не соображу:(, если можно примерчик.

Ответить

Номер ответа: 10
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #10 Добавлено: 26.12.08 03:08
я PB не люблю, но приблизительно так
  1.  
  2. FUNCTION PBMAIN () AS LONG
  3.  
  4.     GLOBAL S1() AS BYTE
  5.     GLOBAL S2() AS BYTE
  6.        
  7.     REDIM S1(&H8000000) '134217729 - элементов, т.е. 134217728 символов плюс 0-терминатор
  8.     REDIM S2(&H8000000)
  9.         
  10.     FillMemory VARPTR(S1(0)), &H8000000, ASC("A")'многа букав
  11.     FillMemory VARPTR(S2(0)), &H8000000, ASC("B")
  12.  
  13.     'S1(&H8000000) = 0 ' нуль-терминаторы строк
  14.     'S2(&H8000000) = 0 '
  15.     
  16.    ' VARPTR(S1(0)) - адрес нулевого элемента массива является адресом строки
  17.     DIM ps1 AS ASCIIZ PTR
  18.     DIM ps2 AS ASCIIZ PTR
  19.     
  20.     ps1 = VARPTR(S1(0))
  21.     ps2 = VARPTR(S2(0))
  22.     'Что ты хотел делать с указателями?
  23. END FUNCTION


Просто запомни, что строки это массив байт в памяти, а адрес строки (указатель) есть адрес первого по счету (нулевого) элемента массива. В каждом элементе масива хранится ASCII-код символа. Последний элемент массива - Ноль. Называется нуль-терминатором.

Ответить

Номер ответа: 11
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #11 Добавлено: 26.12.08 10:51
Протестировал этот код, но к сожелению ситуация не изменилась:
  1. '...
  2. 'Что ты хотел делать с указателями?
  3. MSGBOX STR$(LEN (@ps1))
Все тоже магическое число: 33554432 (32Mb) :(

И еще, я не понимаю этого:
STATIC и GLOBAL строки ASCIIZ могут быть вплоть до 16,777,216 байтов.
Здесь явно указан максимальный размер строки ASCIIZ - 16Mb, но у меня нормально "живут" строки ASCIIZ размером до 32Mb?

Ответить

Номер ответа: 12
Автор ответа:
 alex



Вопросов: 84
Ответов: 453
 Профиль | | #12 Добавлено: 26.12.08 10:56
На надо насиловать свой мозг "массивами байт" и прочей VB-шной шизофренией. Для нормальных людей есть API функции: HeapAlloc и HeapFree. Их и используй для хранения данных

Ответить

Номер ответа: 13
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #13 Добавлено: 26.12.08 11:54
Возможно я ошибаюсь, но мне кажется здесь проблема не в способе выделения буфера для данных, а в самом типе ASCIIZ.
  1. FUNCTION PBMAIN () AS LONG
  2.   LOCAL hHeap AS DWORD
  3.   LOCAL pszStr AS ASCIIZ PTR
  4.   LOCAL szBuffer AS LONG
  5.  
  6.   szBuffer = 44444444
  7.  
  8.   hHeap=GetProcessHeap()
  9.   pszStr=HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, szBuffer)
  10.   FillMemory pszStr, szBuffer, ASC("A")'многа букав
  11.   MSGBOX STR$(LEN (@pszStr))
  12. END FUNCTION
То же самое - 33554432.

Ответить

Номер ответа: 14
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #14 Добавлено: 26.12.08 12:21
Значит врет функция LEN.
Для нормальных людей есть API функции
И другой язык программирования:)
MSGBOX STR$(lstrlen (@pszStr))

Ответить

Номер ответа: 15
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #15 Добавлено: 26.12.08 12:42
Ух ты, а ведь действительно LEN врет.
Спасибо!

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам