PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Вопрос по строке


Вопрос по строке

Сообщений 1 страница 24 из 24

1

Собственно почему *s\s выдаёт ошибку а не стррку с памяти?

Код:
*s.string=@"34556666666"
 Debug PeekS(*s,-1,#PB_Unicode)
Debug *s\s

Отредактировано Sergeihik (14.10.2023 10:45:39)

0

2

Sergeihik написал(а):

Собственно почему *s\s выдаёт ошибку а не стррку с памяти?

Потому что адрес строки присваивается указателю экземпляра структуры, а не строке.
Так работать не будет.

0

3

Пётр написал(а):

Потому что адрес строки присваивается указателю экземпляра структуры, а не строке.
Так работать не будет.

Не правильно как то всё это, чисто с переменными же работает

Код:
*i.integer=AllocateMemory(100)
PokeI(*i,455555)
Debug PeekI(*i)
Debug *i\i
FreeMemory(*i)

0

4

Целочисленная переменная находится непосредственно в структуре, т. к. ее размер известен. Строка может иметь различный размер и в структуре находится указать на нее. Память под строку нужно выделять/освобождать.

0

5

А где тогда хранится строковый литерал "34556666666"? Не в памяти, что ли?

0

6

Замабувараев
что за строковый литерал? Если у строки есть конкретная длина-константа, то такая строка вроде может быть указатель сразу на строку. Например массив строк-констант является последовательностью прилегающих друг к другу данных, а массив строк неизвестной длины является массивом указателей на строки. Внутреннюю кухню можно предполагать. Буква в одинарных кавычках фактически число-код буквы:

Код:
Debug Asc("a")
Debug 'a'

оба вернут 97
литерал это не строка.

Sergeihik
Сколько я использую структуры, вот что я понял: если мы передаём структуру в функцию, то тогда мы используем звёздочку внутри функции (ещё при выделении памяти AllocateMemory + InitializeStructure),  а если мы создаём структуру по ходу пьесы в одном пространстве, то не используем звёздочку. Видимо передача в функцию сама инициализирует память для функции и делает структуру как указатель и не очищает данные. Когда создаёшь структуру внутренний механизм сам определяет что куда положить, здесь s\s это элемент структуры, а "s" или *s это не указатель на строку. То что PeekS её прочитал, так только потому что указатель воткнут в указатель структуры и там остался, а PeekS прочитал с этого указателя, а попробуй манипулировать данными, чтобы произошло перевыделение памяти, это как если поменять расширение у файла html на zip, от этого файл не откроется как архив, так и структура содержит невалидный указатель, какие-то бинарные данные, которые не ссылаются ни на что, а то что PeekS это прочитал это не показатель валидности данных, а только показатель что в якобы в структуре указатель на строку, которую он прочитал.

Код:
Define s.String
s\s = "34556666666"
t =  PeekI(s) ; это указатель t в указателе s
Debug PeekS(t,  -1, #PB_Unicode) ; в указателе t данные на строку

указатель например 8 байт (в x64), в твоём примере он из числа "34556666666" возьмёт первые 8 байт в бинарном виде и воспримет их как указатель, но они могут ссылаться за пределы области выделенной памяти для программы.

Пример из справки, надо создать указатель на указатель, тогда будет работать.

Код:
*Text = @"Hello"
*Pointer.String = @*Text
Debug *Pointer\s 

На сколько я понимаю строка "Hello" останется неприкосновенной в программе, а механизм структуры перевыделит память если будет записана строка более длинными данными.

Отредактировано AZJIO (16.10.2023 16:30:33)

0

7

Замабувараев написал(а):

А где тогда хранится строковый литерал "34556666666"?

Нужно конкретизировать вопрос.
Желательно вместе с кодом.

Замабувараев написал(а):

А где тогда хранится строковый литерал "34556666666"? Не в памяти, что ли?

Все хранится в памяти включая константы.

AZJIO написал(а):

Видимо передача в функцию сама инициализирует память для функции и делает структуру как указатель и не очищает данные.

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

AZJIO написал(а):

На сколько я понимаю строка "Hello" останется неприкосновенной в программе, а механизм структуры перевыделит память если будет записана строка более длинными данными.

Нет.

Код:
*Text = @"Hello"
*Pointer.String = @*Text
Debug *Pointer\s

Debug "Hello"
PokeS(@*Pointer\s, "1234")
Debug *Pointer\s
Debug "Hello"  ; Будет "1234"

0

8

Sergeihik написал(а):

Собственно почему *s\s выдаёт ошибку а не стррку с памяти?

Потому что строковый тип это нечто большее, чем просто указатель на некую любую область памяти.
Возможный аналог с другими языками программирования - "объект типа string".

0

9

Пётр написал(а):

Нет.

Потому что пере выделение памяти не происходит.  Также интересно - строка является частью тела программы, то есть не динамическое пространство памяти выделенное программе. Если писать данные в тело программы это в каком то виде нарушение исполняемого файла.

0

10

AZJIO написал(а):

Если писать данные в тело программы это в каком то виде нарушение исполняемого файла.

Загруженного в память.
На диске содержимое файла не меняется.

0

11

Пётр
Я считал что исполняемая часть кода загруженная в память не меняется. То есть все переменные меняются непосредственно в теле программы и не создаёт их копий?

0

12

Не проще ли посмотреть, что там генерирует компилятор?
В asm в секции .data будет инструкция ассемблера DW, определяющая содержимое строки плюс завершающий ноль. И да, строку можно изменить записав туда по адресу что-нибудь.

0

13

AZJIO написал(а):

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

Содержимое памяти можно изменить.
Исполняемый файл не грузится в память как он есть на диске, а загружается по секциям. Это позволяет к примеру загрузить секцию .code в одном экземпляре для всех запущенных копий приложения, а другие секции содержащие константы и переменные, будут загружены для каждой копии в отдельности.

0

14

То есть все переменные меняются непосредственно в теле программы

Несмотря на то, что в файле исходного кода переменные и код смешаны, в скомпилированном екзешнике ничего не смешано.
Переменные и код разнесены по разным секциям.
Код хранится в специальных секциях, переменные — в стеке или в других секциях. Меняя переменные вы меняете только байты в стеке, секции кода при этом не затрагиваются.

0

15

Пётр написал(а):

Потому что адрес строки

А в чём отличие этого кода от того что это адрес динамической памяти присвоенный указателю структуры(а не программной секции)
ну и по указателю структуры записана строка ,только вот тогда peeks(нужно указатель на указатель)?

Код:
Global *s.string=AllocateMemory(50)
*s\s="34556666666";
 Debug *s\s
 Debug PeekS(@*s\s,-1,#PB_Unicode)

FreeMemory(*s.string)
;предыдущий код
*s.string=@"34556666666"
 Debug PeekS(*s,-1,#PB_Unicode)
Debug *s\s
;;;;;;;;;;;;;;;;;

0

16

Sergeihik
Указателю структуры строки должен присваиваться указатель на существующую строку. В указателе храниться указатель на строку, его ширина 8 байт, для указателя строки не нужно выделать 50 байт с отсутствием указателя на саму строку. Как это будет работать? Это разные типы. В одном случае указатель на выделенную память, в другом случае указатель на структуру. Они разные по содержимому/устройству.

AllocateMemory(50) выделяет 50 байт и даёт пользователю указатель на позицию где эти 50 байт начинаются. Структура это указатель на указатель строки, то есть указатель на 8 байт в котором находится указатель на строку. Если его поместить в 50 байт, то первые 8 байт будет пустым, а там должен быть указатель, остальные 42 байта будут бессмысленным прицепом. А строки вообще не будет. И Windows не сможет обратиться к данным (к строке), так как скажет что указателя "0" не существует.

Отредактировано AZJIO (12.11.2023 19:23:44)

0

17

Sergeihik, ваш код работать не будет.
Чтобы он работал, структура должна содержать строку фиксированного размера.

Код:
Structure str
  s.s{100}
EndStructure

*s.str=AllocateMemory(SizeOf(str))
*s\s="34556666666";
Debug *s\s
Debug PeekS(@*s\s,-1,#PB_Unicode)

FreeMemory(*s)
;предыдущий код
*s=@"34556666666"
Debug PeekS(*s,-1,#PB_Unicode)
Debug *s\s

0

18

AZJIO написал(а):

Указателю структуры строки должен присваиваться указатель на существующую строку. В указателе храниться указатель на строку, его ширина 8 байт, для указателя строки не нужно выделать 50 байт с отсутствием указателя на саму строку. Как это будет работать? Это разные типы. В одном случае указатель на выделенную память, в другом случае указатель на структуру. Они разные по содержимому/устройству.

AllocateMemory(50) выделяет 50 байт и даёт пользователю указатель на позицию где эти 50 байт начинаются. Структура это указатель на указатель строки, то есть указатель на 8 байт в котором находится указатель на строку. Если его поместить в 50 байт, то первые 8 байт будет пустым, а там должен быть указатель, остальные 42 байта будут бессмысленным прицепом. А строки вообще не будет. И Windows не сможет обратиться к данным (к строке), так как скажет что указателя "0" не существует.

Какая то зацикленность у вас на 8 байт указателя,а нечего что винда у меня х32=4 байта адресация памяти?
По вашей логике указатель на указатель тогда и структура наверное должна быть

Код:
Structure String
  *wstr
EndStructure
а не 
Structure String
  s.s
EndStructure

и как тогда работать с структурой string если надо прочитать строку и записать в память=никак?
или так по чудному как то?

Код:
*s1=AllocateMemory(50)
PokeS(*s1,"34556666666",-1,#PB_Unicode)

*s.string=@*s1

Debug *s\s
For i=0 To 26 Step 2
  Debug PeekU(@*s\s+i)
Next 

 Debug PeekS(@*s\s,-1,#PB_Unicode)

FreeMemory(*s1)
;=============================
*s4=@"34556666666"
*s3.string=@*s4
Debug PeekS(@*s3\s,-1,#PB_Unicode)
Debug *s3\s

Только записать тогда как в память?

Отредактировано Sergeihik (13.11.2023 00:26:08)

0

19

Sergeihik написал(а):

,а нечего что винда у меня х32=4 байта адресация памяти?

Ну хоть в чём то я не прав, что не угадал ОС неизвестного мне компа, хотя это и не была необходимая цель для показа работы строки.

Sergeihik написал(а):
Код:
*s1=AllocateMemory(50)
PokeS(*s1,"34556666666",-1,#PB_Unicode)

*s.string=@*s1

Чтобы получить решение надо определиться каким способом будут получены данные. Чтобы создать строку с данными "34556666666" надо просто str$ = "34556666666". Если это данные в памяти, то надо читать с помощью PeekS(). Если это уже строка то используется приравнивание str$ = "34556666666". Структура *s.String по смыслу та же строка, все действия с ней выполняются также как с переменной str$, то есть поле *s.\s равнозначно str$, но с разницей, строку можно отправить в функцию по указателю, то есть отправить указатель на структуру *s, а в приёмнике указать создание структуры *s.String и внутри функции использовать *s.\s, тогда не происходит копирование строки при передачи данных. При этом к этой динамической строке нельзя относится как к бесконечному буферу, даже если строка передана как буфер в функцию WinAPI, то надо гарантировать что данные в неё войдут, то есть используется Space(), чтобы создать строку нужной длины для последующего использования её как буфера, то есть после вброса данных в неё, с ней можно продолжать работать как со строкой, а при использовании AllocateMemory(50) ты не получаешь строку, ты получаешь область памяти и не можешь работать с этими данными как со строкой. При чём причин несколько, например при использовании PeekS() ты создаёшь переменную, но этот процесс не просто чтение одних данных из памяти в другую часть памяти и хотелось бы просто одни данные как то преобразовать в другие не копируя, но PeekS() ещё и переводит данные в "компьютерный" формат строки, то есть если 3-им параметром стоит #PB_UTF8 или #PB_Ascii, то данные будут ещё и преобразованы в формат #PB_Unicode. То есть если тупо использовать переменную с заданной длинной {100} и взять указатель на данные в формате #PB_UTF8 или #PB_Ascii и приравнять их к переменной, то данные внутри переменной при выводе окажутся другими и поиск FindString() по ним работать не будет при кажущейся удаче.

Sergeihik написал(а):
Код:
For i=0 To 26 Step 2
  Debug PeekU(@*s\s+i)
Next

Перебор строки посимвольно я уже делал в куче функций разными способами, буквально вчера сделал человеку побайтам предлагая перед этим посмотреть готовые примеры. Но при отсутствии реакции если человеку сложно было перестроить посимвольный пример в побайтовый, то дал готовый пример.

Отредактировано AZJIO (13.11.2023 10:43:26)

0

20

Sergeihik написал(а):

винда у меня х32=4 байта адресация памяти

Сейчас это редкость, потому что 4 ГБ ОЗУ мало.

Sergeihik написал(а):

По вашей логике указатель на указатель тогда и структура наверное должна быть

Примерно так и выглядит. Только указатель скрытый и работа с ним средствами PB.

Sergeihik написал(а):

и как тогда работать с структурой string если надо прочитать строку и записать в память=никак?

Работайте со строкой средствами PB. Если не вариант, переходите на указатели.
Не зная задачи сложно что-то посоветовать.

0

21

Код:
Structure Ch_
  _ch.u[0] ; есть такой приём
EndStructure

Define teststr.s 
Define *pch.Ch_
Define i = 0

teststr = "0123456789qwertyйцукен"

*pch = @teststr ; это даёт правильный адрес, нужно только понимать, 
                ; что например после teststr = teststr + "___" он может стать другим 
                ; и его желательно получать каждый раз перед использованием

While (*pch\_ch[i] <> 0)
  Debug RSet(Hex(*pch\_ch[i],#PB_Unicode), 4, "0") : i+1
Wend

0

22

Пётр написал(а):

Сейчас это редкость, потому что 4 ГБ ОЗУ мало.

Да лучше 4гб и проц нормальный относительно чем тормаза на х64 с памятью(на работе купили х64 с виндой 11
так тормозит конкретно,даже файл пурика компилит с 10 раза иначе ошибка(наверное типа время задачи (процесса)истекло?),),пока скомпилит нормально минут 10-20 уходит....... :confused:

Отредактировано Sergeihik (06.12.2023 20:12:09)

0

23

useful написал(а):

useful

Тоже трюк.
ps: только с датасекцией или напутал чего или фасм (может пурик)ложит туда utf-8?
Pss:Это говорит о том что возможность есть так взять типа по offset?
но со структурой string пурик этого не делает.

Код:
Global s.s
Procedure.s Getstroka(*adres)

  !mov dword eax,[p.p_adres]
  !mov dword [v_s],eax
  ProcedureReturn s
EndProcedure

Global *stroka=AllocateMemory(500)
PokeS(*stroka,"34556666666",-1,#PB_Unicode)

 Debug PeekS(*stroka,-1,#PB_Unicode)
 
 Debug  Getstroka(*stroka)
 
 
 PokeS(*stroka,"8iugyuiа46гатраytyi7yyhjygn======Privet это динамическая строка========gро5ираавмор",-1,#PB_Unicode)
  Debug  Getstroka(*stroka)
 
  Debug  Getstroka(?statihescay_stroka)
 
FreeMemory(*stroka)


DataSection
  statihescay_stroka:
  !du '8iugyuiytyi7yyhjygn======Privet=Это статическая строка!======giggddhffyhh',0
EndDataSection

Отредактировано Sergeihik (06.12.2023 20:06:37)

0

24

Sergeihik написал(а):

но со структурой string пурик этого не делает.

И не должен.
Чтобы так работало строка должна быть фиксированного размера Вопрос по строке

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Вопрос по строке