Turing String Manipulation
From Compsci.ca Wiki
Revision as of 14:22, 12 October 2008
Contents |
String Manipulation In Turing
Hello thrill-seekers! So you've decided delve into the terrible and mystifying world of string manipulation, aye? For the next half-hour, you will be my slave. Do what I tell you, and you will learn well. Do otherwise, and you shall... not learn well! Alright, enough of that. Let's start.
What is String Manipulation and why do we care?
String manipulation means, quite simply, manipulating strings. For example, if we take a string that the user inputs (such as Paul Simon, as their user name) we might want to greet the user by saying "Hello ", usersFirstName (in this case, Paul). Or what if we want to prevent the program from crashing when the user does something stupid like enter "qr7" when we want them to input an integer?
Search for a space
Strings allow us to do stuff with a specific character from them. For example,
put "Paul Simon" (1 .. 4)
would output Paul. Or I could do stuff like
if myString (5) = " " then put "I found a space!" end if
But how do we know that the 5th character of myString is a space? We don't. If we want to find one, we can run through a for loop:
for i : 1 .. length (myString) if myString (i) = " " then put "Space found at position ", i end if end for
Notice the use of the length function. Length returns the length of the string, quite simply. In other words, it returns the number of characters in the string. So length ("a") would be 1, and length ("12345") would be 5.
Find the user's first name
Excellent. So now let's say hello to Mr. Simon, only a little less formally:
var name := "Paul Simon" var firstName : string for i : 1 .. length (name) if name (i) = " " then firstName := name (1 .. i - 1) end if end for put "Hello ", firstName, "!"
We go through the whole string searching for a space. As soon as we find one, we set firstName to be everything before that space, then exit the for loop. But what if the user enters his/her full name, ie. Paul Frederic Simon. The program will output "Hello Paul Frederic!" That's not what we want. This is easily fixed, though. We'll just add an exit after we've decided where the first space is. What if the user enters only his first name (ie. "Paul")? The program will crash, because firstName was never assigned anything. We can fix this problem by setting firstName to equal name at the beginning of the program. So, if name contains any spaces, it will chomp them off, otherwise it will just (effectively) use name as the output. Final code looks like this:
var name := "Paul Simon" var firstName := name for i : 1 .. length (name) if name (i) = " " then firstName := name (1 .. i - 1) exit end if end for put "Hello ", firstName, "!"
Find the users last name
This is easy enough: it's just a small modification on the last code.
var name := "Paul Simon" var lastName := name for i : 1 .. length (name) if name (i) = " " then lastName := name (i + 1 .. *) end if end for put "Hello Mr. ", lastName, "!"
Note the user of the asterisk (*). The asterisk represents the last character of the string.
var name := "Paul Simon" put name (*) put name (length(name))
Both of these methods output the same thing. The * is just shorter. Smile Also, note that I removed the exit. This way, if the user's name is set to "Paul Frederic Simon", it will output "Simon" not "Frederic Simon".
Finding the middle name
This one's a little bit trickier.
var name := "Paul Frederic Simon" var middleName := name var firstSpace := 0 for i : 1 .. length (name) if name (i) = " " and firstSpace ~= 0 then middleName := name (firstSpace + 1 .. i - 1) end if if name (i) = " " then firstSpace := i end if end for put "Hello Mr. ", middleName, "!"
In this one, I've used a variable to store the positin of the first space. Then, we continue on looking for the next space. When we find it, we make everything after the first space but before the current space equal to middleName. Also, note the positions of the if statements. Were they to be in reverse order, as soon as a space is found, firstSpace would be given a new value and then the next if statement would be true because firstSpace is no longer 0. So we would end up with an error.
Note that all these things could also be done using the index function.
Converting variable types
This next part is really useful for error-traping. But it's also useful for other things, such as drawing text on the screen using Font.Draw (where you must use a string) The Functions
strint (s : string [base : int]) : int intstr (i : int [, width : int [, base : int]]) : string strreal (s : string) : real realstr (r : real, width : int) : string
A couple things you need to know. First, these are functions. They return a value. That's what the last : typeSpec means: it tells us what kind of value the function will return. Thus, the strint function returns an integer, whereas the intstr function returns a string. Next, anything inside brackets ( () ) are your parameters. These are the things that you pass into the function. In the strreal function, s : string means that I must pass a string into the function. Anything inside square brackets ( [] ) is optional.
Error Proofing
We'll error proof our integer input. The first and basic way to do integer input is like so:
var num : int get num
But that crashes if the user enters "y". So let's fix it.
var input : string var num : int get input num := strint (input) put num
Whoo-whee! It runs! Sure, but we've still got the same problem. The program will still crash if the user enters "y". Why? Basically, strint cannot turn a "y" into a number. strint must return an integer (we know this because of the last : int). If it can't, it halts the program. So, how do we fix this? Well, here's some more nice functions!
strintok (s : string [, base : int]) : boolean strrealok (s : string) : boolean
These functions return boolean values: true or false. They return true if the string can be successfully changed into an integer (or real, in the case of the second function) and false if they cannot. No halting. So let's use them.
var input : string var num : int get input if strintok (input) then num := strint (input) put num end if
And there we have it. It's error proofed. (Well, close enough. The user can still crash the program by inputting lots and lots (255, is it?) of characters.) The next thing to do would be to force the user to input an integer. We can use a loop and an exit statement for this:
var input : string var num : int loop cls locate (1, 1) put "Enter an integer: " .. get input if strintok (input) then num := strint (input) put num exit else put "That's not a number, silly!" delay (1000) end if end loop
We only want to exit when the user enters a integer, like they were told.
Font.Drawing an integer
After error-proofing, this should be really easy. If we want to use Font.Draw to put a number on the screen, we have to first convert it to a string. Why? Because Font.Draw expects it's first parameter to be a string. We know this because:
Font.Draw (textStr : string, x, y, fontID, Colour : int)
Alright, so say we want to draw a number on the screen.
var font := Font.New ("Garamond:26:bold") var num : int get num %error proof this! Font.Draw (intstr (num), 100, 100, font, black)
Easy enough. We could also have simply done
Font.Draw (intstr (10), 100, 100, font, black)
But the first way gets you to error proof it for me. Mwahaha!
ord and chr
Next up, we learn about two new functions.
ord (ch : char) : int chr (i : int) : char
ord takes a single character and returns an integer (that is specific to that character). chr takes an integer and returns a single character (that is specific to that integer). To use these, we need to haul out our ASCII chart. So, open Turing, open the Turing Help Manual (that's code for "press F10"), expand Turing Language, select Keystroke Codes. Find the letter "A". It's ordinal value is 65. So
put ord ("A")
would output 65. Similarly,
put chr (65)
would output the letter "A" (without the quotes).
var s : char := "A" put chr (ord (s)) var i : int := 65 put ord (chr (i))
For any character, s, chr (ord(s)) = s. Also, for any integer, i, ord (chr (i)) = i. These functions are useful for a variety of things. For example, say you want to loop until the user presses Ctrl + Backspace:
var input : string (1) loop getch (input) exit when ord (input) = 127 %crtl + backspace end loop
Or, say you want to output the alphabet to the screen, in lower case letters:
for i : 97 .. 122 put chr (i), " " .. end for
How about converting a string from upper case to lower case?
var upperCaseString := "ROOOOAAAR" var lowerCaseString := "" for i : 1 .. length (upperCaseString) lowerCaseString += chr (ord (upperCaseString (i)) + 32) end for put lowerCaseString
If you don't already know what += means, it simply incriments the variable by whatever is after it.
num += 1
is the same as
num := num + 1
When using strings, it just adds the string (or character) to the end of my string. Note that the ordinal value of any lower case letter is equal to the ordinal value of any upper case letter + 32. Note that this doesn't quite work if your string contains things other than numbers. To fix this: Turing:
var upperCaseString := "RAWR!! HERE ME ROAR!!" var lowerCaseString := "" for i : 1 .. length (upperCaseString) if ord (upperCaseString (i)) >= 65 and ord (upperCaseString (i)) <= 90 then %if it is a capital letter lowerCaseString += chr (ord (upperCaseString (i)) + 32) else lowerCaseString += upperCaseString (i) end if end for put lowerCaseString
Yay! Next up, let's try outputting "Aa Bb Cc ... Yy Zz"
for i : 65 .. 90 put chr (i), chr (i + 32), " " .. end for
Conclusion
So there you have it, string manipulation in a really big nutshell that took a long time to write. Aah, let's let Asian sum things up for me, my fingers are tired: AsianSensation wrote:
Know this though, string manipulation comes with practice, and problem solving is a big part of this. So don't assume knowing all about index will make sure you will be able to solve a question. Index is merely a tool, not the solution.
Replace the word "index" with the words "the stuff covered in this tutorial, whatever that may be" and heed his advice (or wisdom).
Happy string manipulating
Credits
Authour: Cervantes