Inserting text in strings

Just starting out? Need help? Post your questions and find answers here.
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Inserting text in strings

Post by ukandrewc »

Hello

I am just wondering how to insert a string into a string in PB.

I tried using

Code: Select all

Mid(MyString,1,5)="hello"
But that causes a compiler error

Thanks
sec
Enthusiast
Enthusiast
Posts: 792
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Post by sec »

Code: Select all

Procedure.s instr(mstr.s, strinsert.s, pos.l)
  ProcedureReturn Mid(mstr, 1, pos-1) + strinsert + Mid(mstr, pos, Len(mstr)-pos+1)
EndProcedure

a.s = "hello"
b.s = "123"

Debug instr(a, b, 2) ; h123ello
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

or the old classical:

i$ = "123"
x$ = "abcdef"
x$ = Left(x$,3)+i$+Mid(x$,4,63999)
Debug x$

note that mid$() in pure does not allow some variations possible in other basics:

x$ = mid$(x$,5)="12345"
... would be insert 12345 at position 5 in string x$ (so the '1' would be the 5th character)

x$ = mid$(x$,5,3)="12345"
... would replace character 3 characters with 12345 (thus making x$ longer)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Post by ukandrewc »

Thanks all

That's a shame because those methods all require the creation of temporary strings.

In other Basics, mid is faster becuase it just inserts into existing string space. As I am trying to rearrange 400k string, it will add time.

Thank you
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

Here's a ReplaceStringAt procedure that uses pointer manipulation.

You could optimise it further by using Assembler.

Code: Select all

Enumeration ;ReplaceStringAt results
  #ReplaceStringAt_OK
  #ReplaceStringAt_PositionGreaterThanDestinationLength
  #ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength
  #ReplaceStringAt_LengthGreaterThanReplacementLength
EndEnumeration

Procedure ReplaceStringAt(*Pd, *Pr, Position, Length)
  ;Loop through the string to the requested position, ensuring we don't reach the end
  ;of the destination string
  For i = 1 To Position - 1
    If PeekB(*Pd) = 0
      ProcedureReturn #ReplaceStringAt_PositionGreaterThanDestinationLength
    EndIf
    *Pd + 1
  Next i
  
  For i = 1 To Length
    ;as we move through both the source and destination ensure that 
    ;we don't reach the end of either
    If PeekB(*Pd) = 0
      ProcedureReturn #ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength
    EndIf
    If PeekB(*Pr) = 0
      ProcedureReturn #ReplaceStringAt_LengthGreaterThanReplacementLength
    EndIf
    PokeB(*Pd, PeekB(*Pr))
    *Pd + 1
    *Pr + 1
  Next i  
EndProcedure

Procedure assert(Test, Description.s)
  If Test 
    Debug Description + ": Pass"
  Else
    Debug Description + ": Fail"
  EndIf
EndProcedure


;Test a good request
t.s = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 4, 3)
assert(Result = #ReplaceStringAt_OK And t = "123XXX789", "OK")

;If the replacement is shorter than length it is ignored
t.s = "123456789"
Result = ReplaceStringAt(@t, @"XXXXX", 4, 3)
assert(Result = #ReplaceStringAt_OK And t = "123XXX789", "OK")

;If the position is off the end of the destination the string
;will remain unchanged.
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 11, 3)
assert(Result = #ReplaceStringAt_PositionGreaterThanDestinationLength And t = "123456789", "PositionGreaterThanDestinationLength")

;If the replacment runs off the end of the destinatino we
;change what we can but destination is not extended.
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 8, 3)
assert(Result = #ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength And t = "1234567XX", "PositionPlusLengthGreaterThanDestinationLength")

;If replacement is shorter than the given length we replace what we have
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 4, 5)
assert(Result = #ReplaceStringAt_LengthGreaterThanReplacementLength And t = "123XXX789", "LengthGreaterThanReplacementLength")
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

ucandrewc, you didn't read my sample properly :-)

anyway, 400k doesn't fit in a pb string, so that example is irrelevant :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Post by ukandrewc »

Hello All

Thanks GedB, I forgot that you can use pointers in PB. I only use it occasionally to create DLL's when VB can't cope.

blueznl: I may wrong but the line:

Code: Select all

x$ = Left(x$,3)+i$+Mid(x$,4,63999)
would create a working string before assigning it to x$ ??

Also, I have passed a 400K string to PB from VB, and am able alter and pass it back. Is this not supposed to happen?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Post by wilbert »

ukandrewc wrote:Also, I have passed a 400K string to PB from VB, and am able alter and pass it back. Is this not supposed to happen?
When you use a PB function that returns a string, the function stores the result in a buffer and the application retrieves that string from the buffer and assigns it to the variable the result should be assigned to.

The standard buffer size is 64000 bytes. If you manipulate a string yourself, without using this buffer, a 400KB string is no problem at all. If you do want to use such a string with the PB functions, you have to increase the buffer size. For testing purposes I worked with a 4 megabyte string that way without any problems.
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Post by ukandrewc »

Thanks for the info wilbert.

I assume that you mean the working buffer space? If so how do you increase it?

I have used the following:

Code: Select all

ProcedureDLL.l SortString(Str.s)
x$=mid(Str,300000,10)
debug x$
Which is fine for my needs as I am only need to find strings of <100 characters.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

300000? can't be, should be max 63999
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Post by ukandrewc »

This is the VB code

Code: Select all

test = Space$(100010)
Mid$(test, 100000, 10) = "hello mum!"
TestString test
This is the PB code:

Code: Select all

ProcedureDLL TestString(Test.s)
MessageRequester(Str(Len(Test)),Mid(Test,100000,10))
EndProcedure
It works - but if you say it can't, then I will use it but pretend that it doesn't :roll:

Andrew
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Oh, my aching sides

Post by Fangbeast »

ukandrewc wrote: It works - but if you say it can't, then I will use it but pretend that it doesn't :roll:

Andrew
Thanks, I just fell off the chair laughing and hurt myself:)
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

hehe.

There is a thread here somewhere where large strings were discussed. (I can't find the thread now so maybe it was in th bugs area and dopped or maybe I am searching badly - but I remember seeing it)

From recollection (vague) the conclusion was that very large strings give the illusion of being OK, but cause probs down the track. There was also some sort of work-around which was hotly argued.
@}--`--,-- A rose by any other name ..
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Post by wilbert »

Code: Select all

; free the old string buffer

! pushd [_PB_StringBase]
! pushd 0
! pushd [_PB_MemoryBase]
! call _HeapFree@12

; allocate a new string buffer of 512KB

! pushd 524288
! pushd 8
! pushd [_PB_MemoryBase]
! call _HeapAlloc@12
! mov [_PB_StringBase],eax

; create a 400KB string

myLongString.s = Space(409600)

Debug Len(myLongString)
This works fine for me.
What could cause problems is if there are string functions with a loop inside that is based on a 16 bit counter (for example in asm cx instead of ecx) but I don't know if there are PB functions like that.
ukandrewc
User
User
Posts: 31
Joined: Fri May 28, 2004 12:07 am

Post by ukandrewc »

Thanks wilbert, that is a great help.

I mainly use PB for creating faster routines to call from VB.

I hadn't realised about the string limit - probably because I tend to pass strings from VB.
Post Reply