Fill up a string with given char

Hello

I’m probably not new with this case. I would like to fill up a given string value with a given char. I.e.:

Fill up “1111” on the right by “0” to the max length of 8 → Output: “11110000

In the most other languages this function is called “LPAD” and “RPAD”. I was checking the String functions and couldn’t find any similar to this, maybe I just overlooked it or searched in the wrong documentation place. This function is so basic I can’t imagine it doesn’t exist in Xojo.

Sure, I see a workaround like adding “00000000” to the given string and then cut it down to the wanted length (2 operations).

Just wondering if this function really doesn’t exist in Xojo.

Background: I’m working with Binary strings and found out that ToBinary never returns a filled (length of 8,16,24, …) Binary and there is no option to get in the wanted Binary length.

Here’s an extension function that you can put in a module for left or right padding:

Public Function Pad(extends input as String, padCharacter as String = "0", left as Boolean = True, toLength as Integer = 16) As String
  '// Example usage
  '   Var s as String = "1011"
  '   s = s.Pad("0", False, 8)
  '   
  '   Result: 10110000
  var data() as String = input.ToArray( "" )
  var originalLength as Integer = data.LastIndex
  
  for index as Integer = originalLength to toLength - 2
    if left then
      data.AddAt( 0, padCharacter )
    else
      data.Add( padCharacter )
    end if
  next
  
  Return String.FromArray( data, "" )
End Function
1 Like

If you want, you can use my routine

Var s As String
s = “222”
TextField1.Text = s
s.remplir ( “0” , 20 )
TextField2.Text= s

Méthode remplir:

// byref  Extends source as String, caracter as string, nombre as integer
’ Methode a copier :
’ Var s As String
’ s.remplir ( “X” , nombre )

For i As Integer = source.Length To nombre
source = source + caracter
Next
 
Exception err
Break
1 Like

Every time you do this the whole string is duplicated, which for long strings makes it very slow.

Thank you for this information.

Indeed it is very slow

My test :

Longueur: 100 000 caracteres

Ajout de 100 caracteres

Temps d’exécution: Ticks: 17 - Secondes: 0.2833333

It is a very bad idea !

If you are doing a lot of string concatenation and your strings can be expected to get long you can use the following:

Function FastConcat()
   // Declare an empty MemoryBlock
   // BinaryStream will make the block larger as required
   Var mResult As New MemoryBlock( 0 )
   // Setup a BinaryStream to the memory block
   Var bsResult As New BinaryStream( mResult )

   // Perform some concatenation
   For Counter as Integer = 0 to 1000000
      bsResult.Write( "Some String" )
   Next

   // Close the stream
   bsResult.Close

   If mResult.Size = 0 Then
      Return ""
   Else
      Return mResult.StringValue( 0, mResult.Size, Encodings.UTF8 )
   End If

End Function

It will be significantly faster.

2 Likes

Thanks everyone for all the solutions. So as you all offer an own solution there seems no Xojo function available. I test all yours and implement one. Performance might not be my issue as I only want to fill up to 8 bits (1 byte).

For this use case, couldn’t you just add eight zeroes and then take the left of the resulting string?

var resultingString
resultingString = "1111" + "00000000"
resultingString = resultingString.Left(8)

I have two functions that makes this pretty easy. The first is a Replicate function and then I created a PADL and PADR so I could pad on either side of a value.

FUNCTION Replicate(Char As String, Number as integer) As String
'---  DUPLICATES A CHARACTER X NUMBER OF TIMES
Dim cString As String = ""
If char <> "" And Number <> 0 Then
  For i As Integer = 1 To Number
    CString = CString + Char
  Next 
End 

Return CString
FUNCTION PADL(String2Pad As String,Length as Integer, PadChar As String) As String
Dim nLen As Integer
String2Pad = String2Pad.Trim
nLen = String2Pad.Length
Return Replicate(PadChar,Length - nLen) + String2Pad
FUNCTION PADL(String2Pad As String,Length as Integer, PadChar As String) As String
Dim nLen As Integer
nLen = String2Pad.Trim.len
RETURN String2Pad.Trim + REPLICATE(PadChar,Length - nLen)

I migrated from the Visual Foxpro world and these functions were built in.

Here’s a little optimization trick - using the Static keyword in the Replicate function, repeated calls to Replicate (with the same parameters) will be much faster.

function Replicate(c as string, n as Integer) as String
  Static s as String = ""

  // if we already created the string with the same values (c and n) then
  // simply return it, rather than re-creating it
  if s.length = n and left(s, c.length ) = c then
    return s
  end if
  // otherwise, create the repeated string
  for i as integer = 1 to n
    s = s + c
  next
  return s
end if

You could combine this technique with the memoryBlock technique from @Ian_Kennedy to get a really fast version.

This makes this function not reentrant, it can’t be used in a preemptive concurrent system.

You could also never use it again with another string :innocent:

See why

External image

1 Like

Yep, as Tim observed, there’s a bug in your idea beyond the use of static for a dynamic content.

Another fast character repeating function.

On my M1
100,000 characters, unprimed takes 250 microseconds or 0.25 milliseconds.

Public Function RepeatChars(ch as string, count as integer) As String
  Static chars As String = ""
  
  // Only allow single characters
  If ch.Length > 1 Then
    Raise New UnsupportedOperationException
  End If

  // make sure there's at least one character
  If chars = "" Then
    chars = ch
  End If
  
  // Make sure we're dealing with the right character
  If chars.Left(1) <> ch Then
    chars = chars.ReplaceAll(chars.Left(1), ch)
  End If
  
  // keep doubling until we have at least the number we need
  While chars.Length < count
    chars = chars + chars
  Wend
  
  // Return the count that we need
  Return chars.Left(count)
End Function

Good catch - the bug was failing to clear the value of S before rebuilding it.

Fixed:

function Replicate(c as string, n as Integer) as String
  
  #pragma BackgroundTasks false

  Static s as String = ""

  // if we already created the string with the same values (c and n) then
  // simply return it, rather than re-creating it
  if s.length = n and left(s, c.length ) = c then
    return s
  end if

  // otherwise, create the repeated string

  s = "" // clear the existing cached string (if any)

  for i as integer = 1 to n
    s = s + c
  next
  return s
end if

Another good point.

However, lots of the Xojo frameworks are not reentrant either, so if you are using Preemptive threading, you would probably shoot yourself in the foot elsewhere, too :slight_smile:

That’s an invalid point. I’m used to write correct code in preemptive mode since the 80’s. If the Xojo framework is ok, I can write correct code. As Xojo is not a single thread system anymore, writing reusable functions with such concerns in mind is important.

Interesting code.
I’m just seeing a potential danger: if you pass “” for ch, you may get an infinite loop.

Just for the sake of hotfixing this, change the

  // Only allow single characters
  If ch.Length > 1 Then
    Raise New UnsupportedOperationException
  End If

to

  // Only allow single characters
  If ch.Length <> 1 Then
    Raise New UnsupportedOperationException
  End
1 Like
Public Function Replicate(str As String, times As Int32) As String

  // Binary string replication, by Rick A. (2025)
  
  // I had this idea based on the Greg O. idea of producing a string by doubling a char
  // until a big enough string and cutting the exact size
  // That doubling screamed binary, so I though...
  // Let's try the exact accumulation, it may be optimal and a small code
  
  // Replicate() replicates strings n times, but faster than usual for large ones
  
  
  Var pad As String = ""
  
  Do Until times <= 0
    If (times And 1) = 1 Then pad = pad + str
    If times > 1 then str = str + str
    times = times \ 2
  Loop
  
  Return pad
  
End Function

######### Test: ##########

For n as integer = 0 to 32
  
  Var s As String = Replicate("X", n)
  
  System.DebugLog s.Length.ToString + " -> " + s
  
Next

For n as integer = 0 to 32
  
  Var s As String = Replicate("Rick", n)
  
  System.DebugLog s.Length.ToString + " " + n.toString + " -> " + s
  
Next

Break

############ Results ############

Summary
09:19:25 : tt.exe Launched
         : 0 -> 
         : 1 -> X
         : 2 -> XX
         : 3 -> XXX
         : 4 -> XXXX
         : 5 -> XXXXX
         : 6 -> XXXXXX
         : 7 -> XXXXXXX
         : 8 -> XXXXXXXX
         : 9 -> XXXXXXXXX
         : 10 -> XXXXXXXXXX
         : 11 -> XXXXXXXXXXX
         : 12 -> XXXXXXXXXXXX
         : 13 -> XXXXXXXXXXXXX
         : 14 -> XXXXXXXXXXXXXX
         : 15 -> XXXXXXXXXXXXXXX
         : 16 -> XXXXXXXXXXXXXXXX
         : 17 -> XXXXXXXXXXXXXXXXX
         : 18 -> XXXXXXXXXXXXXXXXXX
         : 19 -> XXXXXXXXXXXXXXXXXXX
         : 20 -> XXXXXXXXXXXXXXXXXXXX
         : 21 -> XXXXXXXXXXXXXXXXXXXXX
         : 22 -> XXXXXXXXXXXXXXXXXXXXXX
         : 23 -> XXXXXXXXXXXXXXXXXXXXXXX
         : 24 -> XXXXXXXXXXXXXXXXXXXXXXXX
         : 25 -> XXXXXXXXXXXXXXXXXXXXXXXXX
         : 26 -> XXXXXXXXXXXXXXXXXXXXXXXXXX
         : 27 -> XXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 28 -> XXXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 29 -> XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 30 -> XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 31 -> XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 32 -> XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
         : 0 0 -> 
         : 4 1 -> Rick
         : 8 2 -> RickRick
         : 12 3 -> RickRickRick
         : 16 4 -> RickRickRickRick
         : 20 5 -> RickRickRickRickRick
         : 24 6 -> RickRickRickRickRickRick
         : 28 7 -> RickRickRickRickRickRickRick
         : 32 8 -> RickRickRickRickRickRickRickRick
         : 36 9 -> RickRickRickRickRickRickRickRickRick
         : 40 10 -> RickRickRickRickRickRickRickRickRickRick
         : 44 11 -> RickRickRickRickRickRickRickRickRickRickRick
         : 48 12 -> RickRickRickRickRickRickRickRickRickRickRickRick
         : 52 13 -> RickRickRickRickRickRickRickRickRickRickRickRickRick
         : 56 14 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 60 15 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 64 16 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 68 17 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 72 18 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 76 19 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 80 20 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 84 21 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 88 22 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 92 23 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 96 24 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 100 25 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 104 26 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 108 27 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 112 28 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 116 29 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 120 30 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 124 31 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
         : 128 32 -> RickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRickRick
09:20:01 : tt.exe Ended