Chapter 9. Manipulating Strings

CONTENTS
  •  String Object Form
  •  Methods of the String Object Explored
  •  Summary

Whereas storing the string data type in a variable is straightforward enough, manipulating a string can be much more difficult. After you have a string, you'll often want to change it, extract just a portion, or analyze the characters contained within it. Perhaps you want to automatically capitalize the first letter in each word of a string. Or maybe you want to compare the user's input text to a list of correct answers. Using the features of Flash's String object, you can manipulate strings the way a word processor can "find and replace" and much more.

Often the values for your string variables will come from the user; that is, a user will type text into an input text field. Gathering such string data is explained in detail in Chapter 10, "Keyboard Access and Modifying Onscreen Text," when the Key, TextField, TextFormat, and Selection objects are covered. (The order I chose might seem backwards; you can't manipulate a string before you acquire it.) In any event, just realize that you need to populate your variables with strings first. In fact, it's realistic that your string variables can be populated without the user. For example, you may have a list of cities that populates an array. You could hard-wire this at the beginning of your movie. The point is that there's a lot you can do with strings with or without the user's input.

In this chapter you will:

  • Learn the basics of the String object.

  • Integrate the String object's methods for advanced applications.

  • Leverage your knowledge by comparing the String object to other objects.

String Object Form

I'll first explain the easy way to think of the String object, and then I'll provide the messy details that although important will probably never affect you in any practical manner. The String object has several methods and one property (length) see Figure 9.1.

Figure 9.1. All the String object's methods (and one property) are found in the Toolbox list of the Actions panel.

graphics/09fig01.gif

You can write an expression using the methods or property in this form:

anyString.method()  anyString.property

Recall that methods (like functions) always include parentheses that will hold optional parameters. The preceding example shows a variable (anyString) that contains a string for a value can be used with any method or property. For example, the toLowerCase() method converts the string to all lowercase characters and returns the result. If anyString happens to equal "Phillip", the following expression would return (that is, "turn into") "phillip":

anyString.toLowerCase()

You could actually use the literal version "Phillip".toLowerCase(), but more likely you'd want to write an expression that changes based on the value of a variable (anyString). Either way, the form is quite simple.

The only property is length. (And, unlike properties of clips, this one doesn't have an underscore at the beginning of its name.) Using anyString.length returns the number of characters in the string (anyString).

It doesn't get much harder than that. Some methods require a parameter or two. For example, charAt(index) requires the parameter (index) to specify which character you're trying to get. For example, "Phillip".charAt(2) returns "i" (because the first character is located in "index" 0 it counts 0, 1, 2, 3, and so on). We'll look at some practical uses for the different methods in the next section. Notice, it really is pretty simple.

Esoteric String Object Details

Before moving on to a more practical discussion, I should explain a few details. First, all methods of objects require that an object has to be instantiated. In the case of the Movie Clip object, it simply requires that you have an instance on the Stage before you can refer to any properties or methods. The methods of the String object are special, however, because you don't have to first instantiate the object manually. When you use a method (or property) on a variable or string literal (like all the earlier examples), Flash automatically instantiates a temporary String object, does the method's operation, and then discards the object. You don't have to care because it's automatic. When you learn more about objects in Chapter 13, "Homemade Objects," you might learn to love this feature of the String object.

You can instantiate a String object if you want. (But I can't think of a practical reason why you'd want to.) The way you instantiate any object (except a Movie Clip object, which you just drag onto the Stage) is by using the new constructor. (Think of a "constructor" as something that constructs a new instance of object type in this case, String.) Here's an example of creating a new String object and placing it entirely within a variable:

myObjectVar=new String("phillip")

Even though I don't have a practical reason to actually instantiate a String object, I want to point out something confusing. The function called String() is completely different from new String(). String() simply returns a string version of whatever is passed as a parameter (between the parentheses). When you preface string () with the word new, you get a completely different result: a new String object. Just as the Number() function ensures that you have a number data type, String() ensures that the expression in the parentheses is in the string data type form.

Another very similar method is the toString() method, which is used like whatever.toString() to return a string version of whatever, as long as the data type of whatever is an object. The toString() method is almost identical to the String() function, except that (as a method) it operates only on objects (Array, Color, and so on, as you'll see in Chapter 12, "Objects"). Depending on the type of object you're using the toString() method on, it will behave slightly differently. For example, when you use toString() on an array, each item in the array will be converted to a string individually (instead of just one big string). You'll learn more about arrays in Chapter 11, "Arrays." The point is that toString() is a little more refined in its behavior than String(). Generally, most of these details are very intuitive if you avoid using the new constructor and simply think of the String() function and toString() method as ways to ensure that a variable is of the string data type.

While we're on the subject of confusing topics, there are several older functions that have the same or similar names as Flash MX's new methods, including those of the String object. Consider, for example, the (old) function length(). length(myString) returns the number of characters in the myString's value. Bear in mind that Flash's older functions are considered to be "deprecated," which basically means that you should avoid them because they're being phased out. (They're leftover from Flash 4.) It's actually easy to tell the older functions from the newer functions because they're listed in the "Deprecated" folder of the Actions panel.

Methods always operate on an object a given String, in the preceding example. The form is always either object.method() or object.property (just like clip instances!). In this case, the "object" is simply the variable that contains the string on which we're operating such as myString.length or myString.substring(). The functions just stand alone and accept a string for a parameter: length(myString) or substring(myString), for example. The cool thing is the rigid rules in ActionScript make phasing out the old stuff easy. That is, the old function random() is totally different from Math.random(), and it's easy to tell which one is which. (Math. clearly follows the new form object.method().)

Methods of the String Object Explored

graphics/icon02.gif

You can use the String object to do some pretty fancy maneuvers. After walking through a few definitions, we'll look at a few examples of how to use it for practical tasks. You can actually learn quite a bit by exploring the Tooltip and code hints that appear in the Actions panel (see Figure 9.2), not to mention the new Reference panel. The following discussion should give you a good background to the String object's methods before we exercise our expression-writing skills to use the String object.

Figure 9.2. In addition to information provided in the Tooltip and code hints, the reference panel is also available.

graphics/09fig02.gif

Zero-Based System

While playing with the String object, you must remember that (as with arrays) counting begins with 0 (not 1). This is called a zero-based system. That is, the characters in "Phillip" are "P" in the zero index, "h" in the first index, "i" in the second index, and so on. Any time you specify an index in a string, you must start by counting 0, 1, 2, and so on. This "counting from zero" technique can mess you up when you consider the only property of strings: length. (The others are methods.) The expression "Phillip".length will return 7 even though the last character is in the sixth index. Although it's obvious when you think about it, it can often trip you up.

Extracting Portions of Strings

On with the fun! The three methods slice(), substr(), and substring() are different versions of the same basic method. These methods will return a portion of the string being operated on. Even though they're practically equivalent, each has a unique feature or two that makes it interesting. It might make sense to become familiar with one and then realize that the other two are available when your favorite becomes unwieldy.

For the following examples, assume that the variable myString equals "ABCDEFGHI".

slice(start,end) returns all the characters from "start" to (but not including) "end." myString.slice(2,4) returns "CD". That is, the character in the second index ("C") to but not including the fourth index ("E"). Special feature 1: If, in either parameter, you want to include a number equal to the index of the last character but you don't know how many characters are present, just use -1. For instance, if you want all the characters from the second index through (but not including) the end, you could use myString.slice(2,-1) which, in our example, would equal "CDEFGH". Special feature 2: If you leave out the second parameter, you'll get all the characters from start through (and including) the last character. That is, myString.slice(2) returns "CDEFGHI".

substr(start,length) returns a total of "length" characters starting with the one in the "start" index. myString.substr(2,4) returns "CDEF". That's because the second parameter (4) specifies that a string of four letters will be returned, starting with the character in the second index ("C"). Special feature: If you leave out the second parameter, you'll get all characters from "start" through (and including) the last character just like the slice() method. (Like I say, it sometimes makes sense to use one of these until you find a need for the others.)

substring(from,to) returns all the characters from "from" to (but not including) "to." myString.substring(2,4) returns "CD" because (just like the slice() method) the second index is "C", and all the characters to (but not including) the fourth index ("E") would include only indexes two and three. The substring() method is the same as slice, except the special features vary. Both have the option of leaving the second parameter blank (and getting a string from the one parameter provided through the end of the string). But only substring() has the feature that when you accidentally use a higher number for the first parameter, the higher and lower numbers are swapped automatically. That is, myString.substring(4,2) also returns "CD". Also, negative parameters will behave as though they were zeros. That is, you cannot specify a "from" or "to" that are below the first index (0) or above the top index (length-1).

Just to make it confusing, there's an old deprecated function called substring().The best way to avoid confusion is to make sure that you never use this function. Remember that you can tell the difference because methods always appear after the string (myString.substring(), for example), whereas the substring() function's form is substring(string,start,length). Just so you know what it does, the substring() function returns a total of "length" characters from the "start" spot (not index) in "string." Therefore, substring(myString,2,4) returns "BCDE". Notice that the 2 parameter is not an index but rather the second character (counting the way you would normally starting with 1). As I said, just avoid using the substring() function, and you won't get confused.

Extracting Characters, Changing Case, and Searching

Before we do a few exercises, let me introduce a couple other methods. When you only want one character, you can use the charAt() method. charAt(index) simply returns the character in the "index" position. Therefore, myString.charAt(2) will return "C". It's pretty simple, really.

charCodeAt(), a sister method, is identical, except instead of returning an actual string version of the character in the particular index, it returns the ASCII code for that character. The ASCII value for "A" is 65, "B" is 66, and so on. The code for "a" is 97, "b" is 98, and so forth. By the way, the old way to convert a string to uppercase was to find its ASCII value, (assuming it was greater than 96) subtract 32 (the difference between 97 and 65), and then convert back to the string value for the resulting code. (You're about to see that this is unnecessary now.) To convert an ASCII number back to a string, use String.fromCharCode(65). Notice you don't use fromCharCode() in the same way you use other methods (attaching it to a particular string), because you're not operating on a specific string. But just to be consistent, you should begin with String. In this way, fromCharCode() acts like all the Math object methods (which always appear as Math.method() but with String verbatim).

The method toLowerCase()returns an all-lowercase version of the string being operated on. myString.toLowerCase() will return "abcdefghi". Remember that none of these methods actually change the string itself. An assignment like this will, however: myString=myString.toLowerCase(). Naturally, toUpperCase() will return an all-uppercase version of the string.

Finally, perhaps the most powerful methods of the String object are indexOf() and lastIndexOf(). These methods will search through your entire string for a pattern (either a sequence of characters or a single character) that you pass as a parameter. They will then return the index at which the pattern is first found. The difference between indexOf() and lastIndexOf() is that indexOf() starts at the beginning and searches forward, whereas lastIndexOf() starts at the end and searches backward. For example, myString.indexOf("A") will return 0 because "A" was found in the zero index. If the pattern provided as a parameter doesn't appear in the string, -1 is returned. Optionally, you can specify that the search should start at a different spot from the very beginning or very end. You just include an additional parameter, as in myString.indexOf("xx",2), which starts from the second index and searches for "xx". Using these methods, you can quickly find where any particular sequence of characters appears within a larger string. The following example shows how you could first determine where the colon appears in the string "username:phillip" and then use substr() to extract just the characters before or after the colon:

theString="username:phillip";  var spot=theString.indexOf(":");  if (spot!=-1){   firstPart=theString.substr(0,spot);    secondPart=theString.substr(spot+1);  }

Notice that because substr() includes characters only from its first parameter to (but not including) its second parameter, I could use spot (the spot found using indexOf()) when assigning the value for firstPart. But when assigning secondPart, I wanted to start with one character past the colon (spot+1). Also, because I didn't include a second parameter, secondPart included everything from spot+1 through the end. Notice that this code works no matter what the value for theString. For example, "city:Portland" works just as well. Finally, the if statement uses the expression spot!=-1 for a condition. Translated, it says "If it's true that spot is not equal to -1, then proceed." Recall that -1 is returned when the indexOf() method can't find the character for which you're searching.

String Object Methods Applied

That was a nice warm-up example. Let's look at a few more complex solutions that involve a taste of some of the other things you've learned so far.

Let's say you want to ensure that the first letter in each word of a string is capitalized. The toUpperCase() method by itself won't work because it will change every character! The following two functions achieve this goal. In pseudo-code: "Loop for as long as it takes to find all the blanks, and then whenever you find a blank, use the toUpperCase() method on just the character that follows the blank." Check out the two functions here:

function capitalizeWords(theString){   var blankFound=-1;    while ( true ) {     theString=capitalize(blankFound+1,theString);      blankFound=theString.indexOf(" ",blankFound+1);      if (blankFound==-1){       return theString      }    }  }  function capitalize(index, aString){   return aString.substr(0, index) + aString.charAt (index).toUpperCase()+aString.substr( graphics/ccc.gifindex+1)  }

This actually took me quite some time to program, but (as always) I just did it one step at a time. I first built the function capitalize(), which will replace an individual character within a string (and return the result). The capitalize() function receives parameters for both an index (that is, which character you want capitalized) and a string (that's the string you want changed). The one-line function builds a string by combining three parts: first, the characters in front of the index (aString.substr(0, index)); then, an uppercase version of just the one character in the index (aString.charAt(index).toUpperCase()); finally, all the characters after the index (aString.substr(index+1)). The last substr() method doesn't include two parameters because I wanted everything from just past the index to the end. (When you leave the second parameter blank, the method returns all characters through the end.) Basically, the capitalize() function combines three parts: before the character, the character, and after the character. Only the character is turned into uppercase. Before I proceeded, I tested the function with a button containing the following (hard-wired) script:

on (release) {   trace(capitalize(7,"phillipkerman"));  }

Once complete, this will display "phillipKerman" in the output window. I tried a few more options, such as capitalizing the first letter or the last letter the point being that I tested this function before moving on to the more complicated capitalizeWords() function.

After I got the capitalize() function working, I built capitalizeWords(). I wanted a loop that would go through an entire string and capitalize every letter that appeared after a blank. Because I didn't know exactly how many times the loop would repeat, I made a loop that "while true" will loop forever. Notice within the loop that if the variable blankFound ever equaled -1 (the if statement if(blankFound==-1)), the line return theString would execute, which jumps out of the function. (Without this escape route, we could have had a true infinite loop on our hands as discussed in Chapter 5, "Programming Structures.") Remember that when using indexOf() and no match is found, -1 is returned. So, the second line in the loop the one that assigns blankFound to the index where a blank is found (theString.indexOf(" ",blankFound+1)) will turn into -1 when no more blanks are found. Notice that the optional parameter blankFound+1 is provided in this indexOf() method (specifying where the search for blanks should start not at the beginning). Without this, indexOf() would keep finding the first instance of " ", but I wanted it to find one, and then find the next. To make sure that it doesn't find the same blank twice, I simply say "start searching on spot past the last one found." On each iteration of the loop, I reassign theString (the string passed as a parameter) to a new value. Specifically, I capitalize the character just past the last blank found using the capitalize() function created earlier (theString=capitalize(blankFound+1,theString)). The only funky thing is that in the first line I initialize the value of blankFound to -1 so that the first time in the loop (when I capitalize character "blankFound+1"), I'm actually capitalizing the character in the 0 position (the first character).

Naturally, this is easier to explain than it is to write (or to interpret). It's interesting, though, that when I explained how it works, I did so in almost the reverse of the order in which it appears. That's not a requirement, but in the case of the "while true" loop, I think the very first thing you must establish is a "way out." I've heard robbers always establish their exit route before proceeding. It's practically the same thing with loops. (You don't want to be stuck in an infinite loop.) Also, because Flash doesn't read the script in a linear order, you shouldn't try to interpret my finished code that way, either. You can go through line by line, but just realize that certain parts might repeat (in a loop) and you might need to jump around to other parts of the script (anytime a function is called).

Alright, that example was a bit of a doozy. Here's one that's a bit less involved.

The getInfo() function accepts a filename (such as "sunrise.bmp") and returns a string in the form "The file sunrise is a bitmap" (or "jpeg" or "text file," and so on). The basic approach is to cut the string into two parts: the part before the period (the prefix) and the part after the period (the extension). Then we use a series of if-else statements to determine what file type the particular extension matches. Finally, we create the string "The file BLANK is a BLANK," but replace the two BLANKs with the prefix and file type, respectively. Here's the code:

function getInfo(filename){   var dotLoc=fileName.lastIndexOf(".");    var prefix=filename.substr(0,dotLoc);    var extension=filename.substr(dotLoc+1);    var filetype;    if (extension=="bmp"){     filetype="a bitmap";    }else if (extension=="txt"){     filetype="a text file";    }else{     filetype="an unknown file type";    }    return "The file \"" + prefix + "\" is " + filetype + ".";  }

Notice that I save a few local variables that I'll need within the function but nowhere else: dotLoc (containing the "last index of" the period); prefix (using substr() to extract all characters from index 0 through dotLoc); and extension (using substr() again, but from the index dotLoc+1 through the end). Then the if-else sequence checks extension against a few known file types and sets the filetype variable accordingly. The last else is a catch-all that simply sets filetype to "unknown." Also, just so that the string follows proper English and uses "a" and "an" appropriately, I included that part in the filetype variable. (Even though it's not really accurate, it's just the way I designed it it's my variable after all.) This technique is also useful when you're building plural or singular words on-the-fly; it eliminates the need for funky things such as "page(s)," for example.

To test this function, make a button with the following code:

on (release) {   trace(getInfo("sunrise.txt"));    //or    //onScreenVariable=getInfo("sunrise.txt");  }

You can probably see that what you've already learned about code structures (statements such as if and while), plus homemade functions will all come in handy when you try to perform elaborate maneuvers with the String object.

There are a couple methods of the String object that I've left out. In particular, I've left out the method split(), which is quite cool. It will convert a string into an array. You just specify a delimiter as a parameter (myString.split(delimiter)). If myString is "phillip,david,kerman", myString.split(",") will return an array with three items ("phillip", "david", and "kerman"). We'll look at this method more in Chapter 11, when we look at arrays.

Finally, I left out the concat() method. It does the same thing as the + concatenation character, except that it will never act like an addition operator (as + will when both operands are numbers). If myString is "Phillip", myString.concat("David","Kerman") will return "PhillipDavidKerman". By the way, you can have as many parameters as you want just be sure to separate each with a comma.

Summary

Wow, each chapter is more fun than the last! Perhaps the best part of this chapter was that we got to apply our previous knowledge to more practical maneuvers. This was our first introduction to an object other than the all-to-familiar Movie Clip object: the String object. In the past, we played with the Math and Number objects a bit but those are a bit different because they're not much more than a suite of functions. That is, you always begin with Math. or Number. The String object is different because the methods operate on specific instances of strings (just like the Movie Clip methods).

Perhaps the String object is a bit unique because there's no "instantiation" step with strings, which, as you'll see, is required with other objects. In any event, it's still a good object because some powerful and useful methods are available. Using any string value as the object gives you access to some very fancy methods. Extracting substrings and changing case are just a couple things you can do to strings. If this isn't fun, I don't know what is!

CONTENTS


ActionScripting in MacromediaR FlashT MX
ActionScripting in MacromediaR FlashT MX
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 41

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net