Reverse a string
sjr51
Is there a simple command to reverse a string?
String s1 = "hello"
String s2 = s1[(strlen(s1)-1) - p]
String s2 = s1[(strlen(s1)-1) - p]
Does not work because p is only used for wave assignment. s1[4,0] doesn't work either as described in the help file. Is there a command to reverse a string that I'm missing or should just build the reversed string using a loop?
Here's an example of how to do this without a loop, though I wouldn't argue that this wins any simplicity contests:
String s1 = "hello"
String s2 = ReverseString(s1) // this works
print s2
s1 = "hellÖ" // Note the umlaut on the last letter
s2 = ReverseString(s1)
print s2 // This is not what you expect
End
Function/S ReverseString(String inputStr)
Variable len = strlen(inputStr)
if (numtype(len) != 0 || len < 1)
return ""
endif
Make/FREE/B/U/N=(len) byteWave
MultiThread byteWave = char2num(inputStr[p])
Reverse byteWave
String reversedString
wfprintf reversedString, "%c", byteWave
return reversedString
End
Note that as the test() function shows, the ReverseString function will give you what you expect if the input string contains only ASCII characters, but if the input string contains any multibyte characters you probably won't get what you expect when you reverse, since the reverse is done at the level of the bytes and not at the level of the Unicode code point or grapheme. If you needed to support reversing of strings containing non-ASCII characters I think you could do so but it would require a lot of effort.
March 15, 2019 at 08:34 am - Permalink
Just for kicks, here's another way to do it. I suspect that this method is slightly faster but it relies on undocumented behavior and therefore is prone to break. Also, it requires that the length of the string be limited to a certain number of bytes. That limit could be worked around, if necessary, by putting the guts of ReverseString2 into a loop and doing the conversion from and to a structure multiple times.
String s1 = "hello"
String s2 = ReverseString2(s1) // this works
print s2
s1 = "hellÖ" // Note the umlaut on the last letter
s2 = ReverseString(s1)
print s2 // This is not what you expect
End
Constant theStringSize = 400
Structure ReverseString2Struct
char theString[theStringSize]
EndStructure
Function/S ReverseString2(String inputStr)
Variable len = strlen(inputStr)
if (numtype(len) != 0 || len < 1)
return ""
endif
STRUCT ReverseString2Struct s
s.theString = inputStr
Make/FREE/B/U tempWave
StructPut s, tempWave
Reverse tempWave
Rotate strlen(inputStr), tempWave
StructGet s, tempWave
return s.theString
End
March 15, 2019 at 08:40 am - Permalink
Something like the following?
Function/S ReverseString(str)
string str
variable length
length = strlen(str)
if(length == 0)
return str
endif
Make/FREE/T/N=(1, length) wv = str[length - 1 - q]
wfprintf str, "%s", wv
return str
End
March 15, 2019 at 09:01 am - Permalink
In reply to Something like the following… by thomas_braun
If you're going to do this with a text wave, you should change the Make command to /T=1. Otherwise Igor will allocate an std::string on the heap for each point in the wave, and that could get moderately expensive for a long string.
March 15, 2019 at 09:15 am - Permalink
@aclight. Good point. Thanks!
March 15, 2019 at 09:23 am - Permalink
Thank you Thomas and Adam. That works great! My use case is for strings of pure ASCII and some of them might be quite long. The final function with Adam's modification works fine.
March 15, 2019 at 09:49 am - Permalink
Just curious, why do you need to reverse a string?
Andy
March 15, 2019 at 09:53 am - Permalink
In reply to Just curious, why do you… by hegedus
Hi Andy, I'm doing manipulations with DNA sequences. I need to take their complement and reverse them.
March 15, 2019 at 01:23 pm - Permalink