Index a string?

Everything else that doesn't fall into one of the other PB categories.
gedumer
User
User
Posts: 48
Joined: Wed Jun 03, 2009 9:04 pm

Index a string?

Post 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?
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Index a string?

Post by ts-soft »

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.
Image
User avatar
Tenaja
Addict
Addict
Posts: 1959
Joined: Tue Nov 09, 2010 10:15 pm

Re: Index a string?

Post 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"
...
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Index a string?

Post 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.......
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Index a string?

Post 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
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Re: Index a string?

Post 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 :lol:
Image
gedumer
User
User
Posts: 48
Joined: Wed Jun 03, 2009 9:04 pm

Re: Index a string?

Post by gedumer »

Thanks to all for the help... I think I got it:)
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Index a string?

Post 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.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Index a string?

Post 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
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
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Index a string?

Post 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).
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Index a string?

Post 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?
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Index a string?

Post 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)
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Index a string?

Post 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
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Index a string?

Post 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.
Post Reply