Page 1 of 1
Index a string?
Posted: Fri Jul 20, 2012 3:26 pm
by gedumer
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?
Re: Index a string?
Posted: Fri Jul 20, 2012 3:44 pm
by ts-soft
Code: Select all
EnableExplicit
Structure StringArray
c.c[0]
EndStructure
Define.StringArray *Char
*Char = @"hello"
Debug Chr(*Char\c[2])
?
Re: Index a string?
Posted: Fri Jul 20, 2012 3:45 pm
by Tenaja
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"
...
Re: Index a string?
Posted: Fri Jul 20, 2012 3:55 pm
by IdeasVacuum
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.......
Re: Index a string?
Posted: Fri Jul 20, 2012 5:01 pm
by wilbert
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?
Posted: Fri Jul 20, 2012 6:07 pm
by moogle
gedumer wrote:Can you index a string like you can in c/c++ and pascal etc.?
No
gedumer wrote:Can something similar be done in Purebasic?
Yes
It's just much longer of course

Re: Index a string?
Posted: Fri Jul 20, 2012 8:19 pm
by gedumer
Thanks to all for the help... I think I got it:)
Re: Index a string?
Posted: Wed Jul 25, 2012 1:42 am
by Thorium
A variation of ts-softs example, that dont need the use of char().
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
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.
Re: Index a string?
Posted: Wed Jul 25, 2012 3:37 am
by skywalk
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.
Very nice Thorium but question below if UNICODE and concatenating a string?
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
Re: Index a string?
Posted: Wed Jul 25, 2012 6:16 am
by Demivec
skywalk wrote:Very nice Thorium but question below if UNICODE and concatenating a string?
@skywalk: here's a theory:
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?
Posted: Wed Jul 25, 2012 6:44 am
by skywalk
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?
Re: Index a string?
Posted: Wed Jul 25, 2012 6:56 am
by Demivec
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?
Try this small change to your code to expose the difference:
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?
Posted: Wed Jul 25, 2012 3:52 pm
by skywalk
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?
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
Re: Index a string?
Posted: Wed Jul 25, 2012 4:13 pm
by Demivec
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
As the lines read they are the address of the pointer *s, which happens to hold the address of the string.