Index a string?
Index a string?
Can you index a string like you can in c/c++ and pascal etc.?
in c:
char str[10] = "hello";
...
if str[2] = 'l'
...
Can something similar be done in Purebasic?
in c:
char str[10] = "hello";
...
if str[2] = 'l'
...
Can something similar be done in Purebasic?
Re: Index a string?
Code: Select all
EnableExplicit
Structure StringArray
c.c[0]
EndStructure
Define.StringArray *Char
*Char = @"hello"
Debug Chr(*Char\c[2])
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

Re: Index a string?
No. But yes, you can accomplish what you want.
In C, there is no String variable type; you just hack in an array, put a zero at the end of the "useful" data, and call it a string. And hope that you never put in too many characters! That is why character referencing is so easy in C--it is just reading an array position. And, why string manipulation is a little convoluted, with strcat() and strcpy(), etc.
In PB, the whole string is treated as the variable contents--its characters are not elements within an array, they are part of the whole contents. Fortunately, we do have numerous string manipulation commands. And since a string character IS just a location in memory, it can be referenced. Unfortunately, it is super bloated compared to C, but on the other hand, some of C's string handling is bloated compared to PB.
Anyway, this is what you want:
mystring.s = "hello" ; "str" is a reserved keyword in PB, so we rename it.
If Mid(mystring, 2, 1) = "t"
...
In C, there is no String variable type; you just hack in an array, put a zero at the end of the "useful" data, and call it a string. And hope that you never put in too many characters! That is why character referencing is so easy in C--it is just reading an array position. And, why string manipulation is a little convoluted, with strcat() and strcpy(), etc.
In PB, the whole string is treated as the variable contents--its characters are not elements within an array, they are part of the whole contents. Fortunately, we do have numerous string manipulation commands. And since a string character IS just a location in memory, it can be referenced. Unfortunately, it is super bloated compared to C, but on the other hand, some of C's string handling is bloated compared to PB.
Anyway, this is what you want:
mystring.s = "hello" ; "str" is a reserved keyword in PB, so we rename it.
If Mid(mystring, 2, 1) = "t"
...
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Index a string?
In C, that's a char array and becomes a string when null-terminated. You could extract the chars from a string and store them in an array.......
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Index a string?
A few other workarounds ...
Code: Select all
Macro CreateType_Char(length)
Structure Char#length
StructureUnion
s.s{length}
c.c[0]
EndStructureUnion
EndStructure
EndMacro
CreateType_Char(10)
MyStr.Char10
MyStr\s = "hello"
If MyStr\c[2] = 'l'
Debug "index 2 = l"
EndIf
Code: Select all
Dim MyStr.c(10)
PokeS(@MyStr(), "hello")
If MyStr(2) = 'l'
Debug "index 2 = l"
EndIf
Code: Select all
Procedure.c CharAt(s.s, index)
Static *result.Character
*result = @s + index * SizeOf(Character)
ProcedureReturn *result\c
EndProcedure
MyStr.s = "hello"
If CharAt(MyStr, 2) = 'l'
Debug "index 2 = l"
EndIf
Re: Index a string?
Nogedumer wrote:Can you index a string like you can in c/c++ and pascal etc.?
Yesgedumer wrote:Can something similar be done in Purebasic?
It's just much longer of course


Re: Index a string?
Thanks to all for the help... I think I got it:)
Re: Index a string?
A variation of ts-softs example, that dont need the use of char().
It's a undocumented feature that you can reference array indexes out of bound if they are declared in a structure with 0 array elements. This is to enable access of any kind of data as array, including strings.
Code: Select all
Structure CArray
s.s{1}[0]
EndStructure
Define String.s
Define *StringA.CArray
String = "Hello"
*StringA = @String
If *StringA\s[2] = "l"
Debug "ok"
EndIf
Re: Index a string?
Very nice Thorium but question below if UNICODE and concatenating a string?Thorium wrote:A variation of ts-softs example, that dont need the use of char().
It's a undocumented feature that you can reference array indexes out of bound if they are declared in a structure with 0 array elements. This is to enable access of any kind of data as array, including strings.
Code: Select all
Structure ScanPBDataTypes
; These take up no memory and are allowed to grow without redim
; when the structure is pointed at a memory buffer.
; ex. *buf\d[i] ; 'i' being incremented in a loop
; Essentially, this is 1 big StructureUnion.
b.b[0] ; byte
w.w[0] ; word
l.l[0] ; long
i.i[0] ; integer
q.q[0] ; quad
f.f[0] ; float
d.d[0] ; double
a.a[0] ; ascii
c.c[0] ; character
u.u[0] ; unicode
s.s{1}[0] ; string, This does not work -> s.s[0] ; *p\s = @x$, *p\s[1] = IMA.
EndStructure
Define s$ = "Hello"
Define *s.ScanPBDataTypes = @s$
Debug *s
Debug PeekI(@*s)
For i = 0 To Len(s$)-1
Debug *s\s[i] + " " + Chr(*s\c[i])
Next i
s$ + " World" ;<-- Expand the string contents
Debug *s ;<-- Starting address should be the same
Debug PeekI(@*s)
CompilerIf #PB_Unicode
*s = @s$ ;<-- Why is this line not required for ASCII but is for UNICODE?
CompilerEndIf
For i = 0 To Len(s$)-1
Debug *s\s[i] + " " + Chr(*s\c[i])
Next i
Last edited by skywalk on Wed Jul 25, 2012 4:01 pm, edited 2 times in total.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: Index a string?
@skywalk: here's a theory:skywalk wrote:Very nice Thorium but question below if UNICODE and concatenating a string?
Code: Select all
Define s$ = "Hello"
;This requires 6 bytes of storage in ascii, 12 bytes in unicode, system reserves 16 bytes minimum for both.
s$ + " World" ;<-- Expand the string contents
;Previous 6 bytes + 6 bytes more = 12 bytes in ascii now needed for storage.
; Does not exceed 16 bytes and so same storage address is used.
;Previous 12 bytes + 12 bytes more = 24 bytes in unicode now needed for storage.
; Exceeds 16 bytes and so requires a new address for more storage (and thus an update to the pointer).
Re: Index a string?
Makes sense Demivec, but I swear I saw the same pointer address before and after concatenation? Unless I am not debugging the right pointer to a pointer of a string?
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: Index a string?
Try this small change to your code to expose the difference:skywalk wrote:Makes sense Demivec, but I swear I saw the same pointer address before and after concatenation? Unless I am not debugging the right pointer to a pointer of a string?
Code: Select all
s$ + " World" ;<-- Expand the string contents
Debug @s$ ;<<-- New Starting address
Debug *s ;<-- Old Starting address is not necessarily be the same
Debug PeekI(@*s)
Re: Index a string?
Thanks Demivec!
I was tricked because the memory count of "Hello World" in ASCII fit in the same address but not in UNICODE.
Expanding the string to "Hello World & Universe" forced a new address for both ASCII and UNICODE.
Now confused by what address 'z' and 'z2' are?
I was tricked because the memory count of "Hello World" in ASCII fit in the same address but not in UNICODE.
Expanding the string to "Hello World & Universe" forced a new address for both ASCII and UNICODE.
Now confused by what address 'z' and 'z2' are?
Code: Select all
Structure ScanPBDataTypes
; These take up no memory and are allowed to grow without redim
; when the structure is pointed at a memory buffer.
; ex. *buf\d[i] ; 'i' being incremented in a loop
; Essentially, this is 1 big StructureUnion.
b.b[0] ; byte
w.w[0] ; word
l.l[0] ; long
i.i[0] ; integer
q.q[0] ; quad
f.f[0] ; float
d.d[0] ; double
a.a[0] ; ascii
c.c[0] ; character
u.u[0] ; unicode
s.s{1}[0] ; string, This does not work -> s.s[0] ; *p\s = @x$, *p\s[1] = IMA.
EndStructure
Define s$ = "Hello"
Define *s.ScanPBDataTypes = @s$
Debug "-- String & Pointer to String Addresses --"
Debug "@s$ = " + Str(@s$) ;<-- address = x
Debug "*s = " + Str(*s) ;<-- address = x
Debug "PeekI(@*s) = " + Str(PeekI(@*s)) ;<-- address = x
Debug "PeekI(@s$) = " + Str(PeekI(@s$)) ;<-- address = y
Debug "PeekI(*s) = " + Str(PeekI(*s)) ;<-- address = y
Debug "@*s = " + Str(@*s) ;<-- address = z
Debug "-- Step through characters of string via index --"
For i = 0 To Len(s$)-1
Debug *s\s[i] + " " + Chr(*s\c[i])
Next i
s$ + " World & Universe" ;<-- Expanding string contents beyond 16 char's
*s = @s$ ;<-- Reassign pointer since String location changes
Debug "-- After expanding String --"
Debug "-- Step through characters of String via index --"
For i = 0 To Len(s$)-1
Debug *s\s[i] + " " + Chr(*s\c[i])
Next i
Debug "-- New String & Pointer to String Addresses --"
Debug "@s$ = " + Str(@s$) ;<-- address = x2
Debug "*s = " + Str(*s) ;<-- address = x2
Debug "PeekI(@*s) = " + Str(PeekI(@*s)) ;<-- address = x2
Debug "PeekI(@s$) = " + Str(PeekI(@s$)) ;<-- address = y2
Debug "PeekI(*s) = " + Str(PeekI(*s)) ;<-- address = y2
Debug "@*s = " + Str(@*s) ;<-- address = z2
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: Index a string?
skywalk wrote:Now confused by what address 'z' and 'z2' are?
Code: Select all
Debug "@*s = " + Str(@*s) ;<-- address = z
Debug "@*s = " + Str(@*s) ;<-- address = z2