String left,mid and right
Monkey Forums/Monkey Programming/String left,mid and right
| ||
Is there some way to perform operations like left/mid/right on strings in monkey? Im surprised those functions are not included in the language :( |
| ||
I've only ever seen those functions in Excel/VB, so they're not exactly common library issue as far as I'm aware. Monkey strings are slice-able though, so what are you wanting to do that you find you can't? |
| ||
To elaborate slightly on what muddy_shoes said: Left(i): str[..i] Right(i): str[i..] Mid(i,j): str[i..j] |
| ||
@muddy_shoes At the moment I need left() for debugging purposes. I want to print floats values using text command. But I dont want to output 20 or so decimals, and would like to truncate the numeric string to the first 5 or 6 decimal place. Also I've been using left,mid and right on lots of occasions before in other languages, so I know Im going to need those functions again for manipulating strings. So the question really is, what alternatives are there in monkey to accomplish the same result as left..etc @warpy Could you please elaborate on your example? How can I use str[..i] to truncate the lenght of characters when printing var value? local value#=Rnd(1.0) Text "value: "+value,x,y |
| ||
Ok, figured it out :) Example left... local value#=Rnd(1.0) Text "value: "+String(value)[..5],x,y |
| ||
This may help:Function Left:String(value:String, index:int) If index<0 then Error "Illegal call. Index must be greater than zero." Return value[..index] End Function Right:String(value:String, index:int) If index < 0 Then Error "Illegal call. Index must be greater than zero." Return value[ - index ..] End Function Mid:String(value:String, index:Int, count:Int) If index < 0 Then Error "Illegal call. Index must be greater than zero." If count < 0 Then Error "Illegal function call. count must be greater than zero." index-=1 Return value[index..(index+count)] End Function Mid:String(value:String, index:Int) If index < 0 Then Error "Illegal call. Index must be greater than zero." index -=1 Return value[index..(value.Length-index)] End Function Instr(value:String, sub:String, start = 1) If start < 0 Then Error "Illegal call. start must be greater than zero." Return value.Find(sub, start - 1) + 1 End Function Function Replace:String( value:String,sub:String,replaceWith:String ) Return value.Replace( sub,replaceWith ) End Function Function Lower:String( str$ ) Return str.ToLower() End Function Function Upper:String( str$ ) Return str.ToUpper() End Function |
| ||
Something like this:Local value#=Rnd(0,1) Print "value: "+String(value)[..5] Note that you have to explicitly cast the number to a string before you can slice it. |
| ||
Crumbs, someone phones me and when I come back two more posts have appeared! |
| ||
Useful functions ziggy, thanks! |
| ||
Thanks ziggy. I'm happy people are taking the time to write these helpful functions. Makes it easier to convert code. |
| ||
http://www.monkeycoder.co.nz/Community/posts.php?topic=269#1729 I made a 'copy & paste' of the BlitzMax functions+some ones personalized. |
| ||
How is it that in all my many posts in this thread I forgot to mention the most important fact: 99% of the time, when you think you can do something with string slices, that is a really bad idea. Truncating numbers is not something you should be doing just by manipulating the string representation of a float. Do this instead: Function round$(value#,places) places = Max(places,0) 'sanity check - you can't round to a negative number of decimal places If value<0 Return "-"+round(-value,places) Local i = Floor(value) 'get integer part value -= i 'take away integer part to be left with fractional part value *= Pow(10,places) Local f = Floor(value) 'round off unwanted digits If value-f>=.5 f+=1 'round up if first digit rounded off is 5 or greater If f = 0 Return String(i) Else Return i+"."+f Endif End Function Main() Local value#=Rnd(100,200) Print "Round "+value+" to " For Local c=0 To 3 Print c+" decimal places: "+round(value,c) Next Print "Round 1.35 to 1 decimal place (round up): "+round(1.35,1) Print "negative pi to 3 decimal places: "+round(-PI,3) End |
| ||
Thanks for the added insight warpy. But there are plenty of other cases where you need to manipulate strings for one reason or another. So why is it such a bad idea to operate on string slices? |
| ||
Generally because the problem you're trying to solve isn't usually just a problem about strings, so the routine you come up with will probably be quite error-prone. |
| ||
This doesnt work well.. Function Right:String(value:String, index:int) Return value[-index..] End I did this for the moment Function Right:String(Strng:String, Length:Int) Local I, Start, Answer:String Length = Length - 1 Start = Len(Strng) - Length For I = Start To Len(Strng) Answer = Answer + Mid(Strng, I, 1) Next Return Answer End Function Ziggy's Function for some reason keep returning the orginal Value as it was |
| ||
Ziggy's works fine for me:Strict Function Main:Int() Local str:String = "Hello" Local newStr:String = Right(str, 2) Print(newStr) Return 0 End Function Right:String(value:String, index:int) Return value[-index..] End Prints out "lo" as expected... |
| ||
Also, Hardcoal,. every time you slice a string you get a new string generated; by putting Mid in a loop, you're generating a lot of garbage. |
| ||
@Raph I thought that when you are out of the Function the Garbage Cleaner Automatically Cleans it... omg thats bad In Ziggys Command I Did This Right(UserLine, Len(UserLine) - Len(UserLineWord)) This should reduce the a word from the user line but instead it returned the same result.. is it also correct for blitzmax this garbage issue? |
| ||
Monkey's GC (or the Targets GC) will clear it up, but it is best not to create junk in the first place. I gather your Len function returns the length of a string... Why dont you use Monkey's functions such as Length etc? Anyway again this works: Strict Function Main:Int() Local UserLine:String = "Hello" Local UserLineWord:String = "lo" Local newStr:String = Right(UserLine, Len(UserLine) - Len(UserLineWord)) Print(newStr) Return 0 End Function Len:Int(value:String) Return value.Length End Function Right:String(value:String, index:Int) Return value[-index..] End Maybe post a runnable example so we know exactly what is your problem. |
| ||
ok i will. its not urgent atm :) |
| ||
I've modified the above function to include parameters validation ala traditional basic. Maybe that was causing you runtime problems, Hardcoal. |