Jump to content

convert tabs to spaces


Recommended Posts

The three candidates for timing are (so far):

The StringRepeat:

Func StringRepeatTest($sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), _StringRepeat(" ", $iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc

The StringLeft:

Func StringLeftTest($sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), StringLeft("        ",$iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc

The StringArray:

Func StringArrayTest($sString, $iTabLen = 8)
  Local $sSpaces[9]=[""," ","  ","   ","    ","     ","      ","       ","        "]
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), $sSpaces[$iSpaceLeft + 1], 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc

Any others?

Code hard, but don’t hard code...

Link to comment
Share on other sites

Preliminary Results based on a short test string:

START ----- StringRepeatTest------

TIMING FOR 1000: 0.303
TIMING PER ITER: 0.000303

END --- StringRepeatTest---


START ----- StringLeftTest------

TIMING FOR 1000: 0.144
TIMING PER ITER: 0.000144

END --- StringLeftTest---


START ----- StringArrayTest------

TIMING FOR 1000: 0.137
TIMING PER ITER: 0.000137

END --- StringArrayTest---

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

Here’s the actual test rig i used if someone wants to validate it:

#include <String.au3>

$str="1234567   123456  12345   1234    123 12  1   "
$str&="1234567  123456  12345   1234    123 12  1   "
$str&="1234567  123456  12345   1234    123 12  1   "
$m=1000

TimeIt("StringRepeatTest")
TimeIt("StringLeftTest")
TimeIt("StringArrayTest")

Func TimeIt($version)

ConsoleWrite ("START ----- "& $version & "------" & @CRLF & @CRLF)

Switch $version
  Case "StringRepeatTest"
     $t1=ms()
     For $n=1 To $m  
        StringRepeatTest($str)
     Next    
     $t2=ms()
     
  Case "StringLeftTest"
     $t1=ms()
     For $n=1 To $m  
        StringLeftTest($str)
     Next    
     $t2=ms()
     
  Case "StringArrayTest"
     $t1=ms()
     For $n=1 To $m  
        StringArrayTest($str)
     Next    
     $t2=ms()
 
EndSwitch

$t3=Round($t2-$t1,6)
$t4=Round($t3/$m, 6) 

ConsoleWrite("TIMING FOR "& $m &": "& $t3 & @CRLF)
ConsoleWrite("TIMING PER ITER: "& $t4 & @CRLF & @CRLF)

ConsoleWrite ("END --- "& $version &"---" & @CRLF & @CRLF & @CRLF)

EndFunc

Func ms()
   Return (@HOUR*3600)+(@MIN*60)+(@SEC*1)+(@MSEC/1000)
EndFunc

Func StringRepeatTest($sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), _StringRepeat(" ", $iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc 

Func StringLeftTest($sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), StringLeft("        ",$iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc 

Func StringArrayTest($sString, $iTabLen = 8)
  Local $sSpaces[9]=[""," ","  ","   ","    ","     ","      ","       ","        "]
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, Chr(9), $sSpaces[$iSpaceLeft + 1], 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

:)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

#include <String.au3>
#include <File.au3>

Local $hTimer = TimerInit()
Local $aFileLines
_FileReadToArray("Temp\AutoIt3Wrapper.au3",$aFileLines)
if @error Then Exit MsgBox ($MB_SYSTEMMODAL,"",@error)
For $i = 1 to $aFileLines[0]
  $aFileLines[$i] = _TabsToSpaces($aFileLines[$i])
Next
_FileWriteFromArray("Temp\AutoIt3Wrapper New.au3",$aFileLines,1)
MsgBox ($MB_SYSTEMMODAL,"",TimerDiff($hTimer))

Func _TabsToSpaces($sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, @TAB, StringLeft("        ",$iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
  Return $sString
EndFunc   ;==>_TabsToSpaces

Just copy AutoIt3Wrapper.au3 file to local test folder

Link to comment
Share on other sites

50 minutes ago, Nine said:

Just copy AutoIt3Wrapper.au3 file to local test folder

Slight change (ByRef) shaves a millisecond or two - less than I expected, but something...

#include <String.au3>
#include <File.au3>

Local $hTimer = TimerInit()
Local $aFileLines
_FileReadToArray("Temp\AutoIt3Wrapper.au3",$aFileLines)
if @error Then Exit MsgBox ($MB_SYSTEMMODAL,"",@error)
For $i = 1 to $aFileLines[0]
  _TabsToSpaces($aFileLines[$i])
Next
_FileWriteFromArray("Temp\AutoIt3Wrapper New.au3",$aFileLines,1)
MsgBox ($MB_SYSTEMMODAL,"",TimerDiff($hTimer))

Func _TabsToSpaces(ByRef $sString, $iTabLen = 8)
  Local $iMod, $iSpaceLeft
  Local $iTabPos = StringInStr($sString, @TAB, 1)
  While $iTabPos
    $iMod = Mod($iTabPos, $iTabLen)
    $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
    $sString = StringReplace($sString, @TAB, StringLeft("        ",$iSpaceLeft + 1), 1, 1)
    $iTabPos = StringInStr($sString, @TAB, 1)
  WEnd
EndFunc   ;==>_TabsToSpaces

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

On 11/10/2020 at 11:39 PM, Zedna said:

Another optimisation tip:

Avoid calling Chr(9) inside loop, instead call it only once before loop $tab=Chr(9) or $tab=@TAB and inside loop use only variable $tab

 

As I said: inside of loop use $tab (not @TAB)

$start = TimerInit()
For $i = 1 To 100000
    $s = "1" & Chr(9)
Next
ConsoleWrite("Chr(9): " & TimerDiff($start) & @CRLF)

$start = TimerInit()
For $i = 1 To 100000
    $s = "1" & @TAB
Next
ConsoleWrite("@TAB: " & TimerDiff($start) & @CRLF)

$start = TimerInit()
$tab = @TAB
For $i = 1 To 100000
    $s = "1" & $tab
Next
ConsoleWrite("$tab: " & TimerDiff($start) & @CRLF)


#cs
Chr(9): 126.61379197976
@TAB: 154.890994068918
$tab: 93.2801592911952
#ce

 

Link to comment
Share on other sites

4 hours ago, Zedna said:

As I said: inside of loop use $tab (not @TAB)

if speed is the need, you need to pull out all the (tab) stops :)

$start = TimerInit()
For $i = 1 To 100000
    $s = "1" & Chr(9)
Next
ConsoleWrite("Chr(9): " & TimerDiff($start) & @CRLF)

$start = TimerInit()
For $i = 1 To 100000
    $s = "1" & @TAB
Next
ConsoleWrite("@TAB: " & TimerDiff($start) & @CRLF)

$start = TimerInit()
$tab = @TAB
For $i = 1 To 100000
    $s = "1" & $tab
Next
ConsoleWrite("$tab: " & TimerDiff($start) & @CRLF)

$start = TimerInit()
For $i = 1 To 100000
    $s = "1" & "    " 
Next
ConsoleWrite("Literal TAB: " & TimerDiff($start) & @CRLF)

#cs 
Chr(9):  91.5255
@TAB:   103.4114
$tab:    60.7188
Literal: 55.084
#ce

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

There is a potential bug with the code using StringLeft.  If $iTabLen is greater than 8, it will not work correctly as the number of spaces provided in StringLeft is 8.  Either the number should be increase, or a check should be made before calling the _TabsToSpaces function (not inside cause it will impact performance).

Link to comment
Share on other sites

On 10/26/2020 at 7:02 PM, Professor_Bernd said:

Excuse my poor English. Was my formulation wrong? Is this formulation better? :think:

What I meant was a function with a reverse conversion direction. If the normal direction is to convert tabs to spaces, then the reverse direction would be to convert spaces to tabs. I think your function is more an undo function than a converter function SpacesToTabs. 

 

Hi @Professor_Bernd,

the following function (_StringSpacesToTab) should work for that case. Here too, as already said, the TabLen parameter is important to obtain the correct result relative to the TabLens of the environment in which the resulting string will be used.
Also, if the input string already contains some @tabs, this function fails, so it would be better to pass the string to the TabsToSpace function first in order to convert any @tabs to spaces before submitting it to this SpacesToTabs function (I hope there are no errors )

Here we go...

#include <string.au3>
_Example()

Func _Example()
    Local $sMyString = "1         2             3                          4" ; <--- random string that contains spaces
    ConsoleWrite($sMyString & @CRLF)
    ; we use 8 as second parametre because the AutoIt console has a Tablen of 8 as well
    ConsoleWrite(_StringSpacesToTabs($sMyString, 8) & @CRLF) ; <- contains @tabs (and residual spaces)
    ; - NOTE -
    ; -------------------------------------------------------------------------------------------------
    ; If input strings contains some @tab, the _StringSpacesToTabs() function fails
    ; so you should call it like this: _StringSpacesToTabs(_StringTabsToSpaces($sMyString)) so to ensure
    ; that no @tabs are contained in the input string.
    ; -------------------------------------------------------------------------------------------------
    ; example
    ConsoleWrite(@CRLF & @CRLF & "... if input string contains also some @tabs ..." & @CRLF)
    $sMyString = @TAB & "Hello         " & @TAB & "Good      " & @TAB & "Morning           <" ; <--- contains spaces and @tab
    ConsoleWrite($sMyString & @CRLF)
    ; first convert @tabs to spaces (if any), then convert spaces to @tabs
    ConsoleWrite(_StringSpacesToTabs(_StringTabsToSpaces($sMyString, 8), 8) & @CRLF)
EndFunc   ;==>_Example

Func _StringSpacesToTabs($sInput, $iTabLen = 8)
    Local Static $iTab = @TAB, $sSpc = ' '
    Local $i1 = StringLen($sInput) ; start from the last char of the string
    While $i1
        ; Check if there is a space before a TabStop position
        While (StringMid($sInput, $i1, 1) == $sSpc) And (Mod($i1, $iTabLen) = 0)
            $iStartSpaces = $i1 ; if so then remember this 'start' position ...
            ; ... and search for any additional spaces (only up to tablen)
            While (StringMid($sInput, $i1 - 1, 1) == $sSpc) And (Mod($i1 - 1, $iTabLen))
                $i1 -= 1
            WEnd
            ; remove found spaces from the string and replace with a @tab
            $sInput = StringLeft($sInput, $i1 - 1) & $iTab & StringMid($sInput, $iStartSpaces + 1)
        WEnd
        ; go to check next char (backwards)
        $i1 -= 1
    WEnd
    Return $sInput
EndFunc   ;==>_StringSpacesToTabs

Func _StringTabsToSpaces($sString, $iTabLen = 8)
    Local Static $iTab = @TAB, $sSpc = ' '
    Local $iMod, $iSpaceLeft
    Local $iTabPos = StringInStr($sString, $iTab, 1)
    While $iTabPos
        $iMod = Mod($iTabPos, $iTabLen)
        $iSpaceLeft = $iMod ? $iTabLen - $iMod : 0
        $sString = StringReplace($sString, $iTab, _StringRepeat($sSpc, $iSpaceLeft + 1), 1, 1)
        $iTabPos = StringInStr($sString, $iTab, 1)
    WEnd
    Return $sString
EndFunc   ;==>_StringTabsToSpaces

 

Edited by Chimp
renamed Function from _StringSpacesToTab to _StringSpacesToTabs

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Hello Chimp.

At the moment I am very busy with my project PSPad4AutoIt3 (editor IDE), for which I try to release the next version before the end of the year. Therefore I could only test your code for a short time.

Your code is cool! I didn't think that the reverse direction, meaning SpacesToTabs would be possible in a useful way. But you have found a solution! Even though there are probably few situations to use this direction, it is always better to have a solution and not need it than to need a solution and not have it. B)

Therefore: Good work! I thank you!  :graduated:

Link to comment
Share on other sites

11 minutes ago, Professor_Bernd said:

... I didn't think that the reverse direction, meaning SpacesToTabs would be possible in a useful way.

me too, it's not that easy to find in fact, that's why I wanted to find it ... B)

15 minutes ago, Professor_Bernd said:

 it is always better to have a solution and not need it than to need a solution and not have it

I agree ... :D

15 minutes ago, Professor_Bernd said:

I thank you!

You are welcome.. :)

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...