Task 11: String Manipulation  


The UCASE$ and LCASE$ Statements
The LTRIM$, RTRIM$, and _TRIM$ Statements
The INSTR Statement
The STR$ and VAL Statements
The LEN Statement
The RIGHT$, LEFT$, and MID$ Statements
The ASC and CHR$ Statements
The STRING$ and SPACE$ Statements
The SWAP Statement
A Quick String Manipulation Demo
Your Turn - LetterCount.BAS
Command Reference

Not all games involve pressing buttons to shoot enemies on the screen. Many of the all time favorites involve entering text to play such as Hangman, Scrabble, crossword puzzles, Boggle and Text Twist just to name few. Luckily QB64 has a rich feature set of commands that allow the programmer to manipulate text entry in many different ways.

The UCASE$ and LCASE$ Statements

When a user answers a program's question, for instance, "What is the capital of Ohio?", how will the user answer? Will the user type in the correct answer? Will the answer be in UPPER or lower case or a cOmbInaTion of both? How do you as the programmer check for all of these variations? The answer lies in turning the user's response into something that can easily be checked. Type the following program in, save it as UCASE.BAS, and then execute it.

As long as the user knows how to spell Columbus the case of the response does not matter. The UCASE$ statement in line 14 returns the string parameter associated with it in all upper case. The LCASE$ statement does just the opposite, returning the string parameter associated with it in all lower case.  Line 14 could have just as easily been:

IF LCASE$(Answer$) = "columbus" THEN

and the program would behave just as it did using UCASE$.

The LTRIM$, RTRIM$, and _TRIM$ Statements

User's do funny things like not enter responses as we programmers expect. You always have to take into account the different ways a response can be entered in the WRONG way by a user for your code to be effective. The example code above will fail if the user enter spaces (presses the space bar) either before or after the word Columbus. The spaces will be seen as legitimate characters typed in by the user.

There are three statements that will remove leading, trailing, and both leading and trailing spaces from a string. LTRIM$ removes leading, or left hand, spaces from a string. RTRIM$ removes trailing, or right hand, spaces from a string, and _RTRIM$ removes both leading and trailing spaces from a string. If you change line 14 in the example code to:


Answer$ will first be converted to upper case and then have both leading and trailing spaces removed from it. Yes, this new line of code looks a bit complicated because one statement is embedded into another. This is a very common thing to do in programming that enables multiple actions to be taken on a parameter at the same time. Simply follow the order of operations to see how the line of code operates. UCASE$ falls inside of _TRIM$'s parenthesis so the UCASE$ statement is acted upon first. Once UCASE$ has returned the upper case form of Answer$ it's _TRIM$'s turn to take that upper case Answer$ and remove the leading and trailing spaces. You now have a string returned that is in both upper case and has had the leading and trailing spaces removed.

You could even change the line of code to read:

Answer$ = _TRIM$(UCASE$(Answer$))

to permanently modify Answer$ by making the changes and then placing those changes back into Answer$ itself. This is handy if you need to reference Answer$ again later in the code as it will save you from having to test for upper case and leading/trailing spaces again.

The INSTR Statement

The previous examples work great for single word answers but those darn users will always test the limits of your code. What if the user were to answer "I think it's Columbus?" Technically the answer has the correct response embedded in the string the user entered but how do we see that in code?

The INSTR statement has the ability to search a base string with a defined search string and return a numeric value of where the search string was found within the base string. Once again let's modify the previous example code to see this in action. When you execute the program type your answer in as "I believe Columbus would be the answer" and see if you are correct.

Figure 1 - This is how Skynet got its start!

INSTR requires a string to search called the base string. In this case the base string is the upper case result of UCASE$, so the entire response entered is converted to upper case. The next parameter that INSTR requires is a string to search for called the search string. In line 14 we supplied INSTR with a search string of "COLUMBUS". If the string "COLUMBUS" is found anywhere within the user's response INSTR will return a numeric value of where it was found. If INSTR is anything other than zero then "Correct!" will get printed since we know that the IF...THEN statement will consider any numeric value other than zero as true.

There is one strange behavior of INSTR that needs to be pointed out. The following line of code will result in a value of 1 being returned.

Location% = INSTR("ABCDE", "") ' null string returns a value of 1

A search for a null string ( "" ) will always result in a positive value being returned (unless you search for a null string within a null string). This may sound like a bug but in actuality every string does contain a null string. You just need to be aware of this behavior if you start receiving a result you did not expect.

INSTR also has another trick up its sleeve. It can find multiple occurrences of the search string in the base string and report back where it finds all of them. Type in the following example to see how this works. Save the code as InstrDemo.BAS when finished.

Figure 2 - The Weather in Spain Seems Nice

The INSTR statement can accept an optional position parameter as seen in line 20 of the code.

Position% = INSTR(Position% + 1, Phrase$, Search$)

Each time an instance of "ain" is found that position is recorded so the next time around Position% + 1 can be used to resume the search through the remainder of the base string. This continues on until Position% becomes zero, meaning no more matches, and ending the loop.

The STR$ and VAL Statements

There will be times when you need to convert a string to a numeric value and a numeric value to a string. The STR$ statement is used to convert a numeric value to a string. The VAL statement is used to convert a string to a numeric value.

LINE INPUT "Enter a number between 1 and 10 > ", Number$
Value! = VAL(Number$) ' convert string to a numeric value

The above example shows a number being asked for however it's being saved in a string variable. The VAL statement is used to convert Number$ into an actual numeric value and then saved into the single type variable Value!. If the characters in Number$ are non-numeric, such as "Hello World", VAL will simply return a numeric value of zero.

INPUT "Enter a number between 1 and 10 > ",Value%
Number$ = STR$(Value%) ' convert numeric value to a string

In this example the opposite is being performed. The numeric value contained within Value% is being converted to a string and then saved into Number$. Positive numeric values converted to strings will always contain a leading space. The space is there for the possibility of a negative value that includes a minus sign. For example:

PRINT "*"; STR$(10); "*" '  * 10* printed to the screen
PRINT "*"; STR$(-10); "*" ' *-10* printed to the screen

You'll need to use either LTRIM$ or _TRIM$ to remove the leading space if you do not wish it to be present.

Number$ = LTRIM$(STR$(Value%)) ' no leading space

The LEN Statement

The LEN statement returns the number of characters contained in a string effectively reporting its length.

Phrase$ = "The rain in Spain falls mainly on the plain."
PRINT LEN(Phrase$) ' 44 is printed to the screen

The RIGHT$, LEFT$, and MID$ Statements

These statements are used to parse, or break apart, a string into smaller pieces. An example of this is when you use the TIME$ and DATE$ statements to retrieve the time and date from QB64. TIME$ delivers the time in the string form "HH:MM:SS" and DATE$ in the string form "MM-DD-YYYY". In order to get the individual hours, minutes, and seconds from TIME$, and the individual month, day, and year from DATE$ you'll need to to use the LEFT$, RIGHT$, and MID$ statements. Type the following example program into your IDE to show this. Save the code as ParseDemo.BAS when finished.

Figure 3 - Time to Make the Donuts!

The LEFT$ statement is used to grab a predetermined number of characters starting at the left-hand side of the string. In line 30 of the program LEFT$ is used to parse just the month portion of DATE$.

Month% = VAL(LEFT$(DATE$, 2)) ' parse MM from MM-DD-YYYY

A statement within a statement within a statement! WooHoo, as I stated before this is a common occurrence in programming. Let's break it down.

DATE$ returns a string in the form of "MM-DD-YYYY". Then we plug that string into LEFT$:

LEFT$("MM-DD-YYYY", 2) ' get the first two left hand characters from MM-DD-YYYY

LEFT$ grabbed the first two characters of the string which equals the month. In our example this would be "04" or April. The VAL statement is now used to convert that string into an actual numeric value:

VAL("04") ' convert to a true numeric value

LEFT$ was also used in the same manner on line 33 to get the current hour from TIME$.

Hours% = VAL(LEFT$(TIME$, 2)) ' parse HH from HH:MM:SS

In line 31 the MID$ statement is used to parse out a string from within DATE$:

Day% = VAL(MID$(DATE$, 4, 2)) ' parse DD from MM-DD-YYYY

MID$ starts at position 4 of the string and then parses 2 characters starting at that position.

And finally the RIGHT$ statement is used  to parse out the remaining date in line 32:

Year% = VAL(RIGHT$(DATE$, 4)) ' parse YYYY from MM-DD-YYYY

Here is another example program that uses string manipulation to create a scrolling LED sign. Due to the length of this example the source code has been included entitled LEDSign.BAS so you can simply load it into your IDE if you wish. As always however I encourage you to take the time to type this program in by hand.

Figure 4 - A Scrolling LED Sign

Don't let the length of this source code scare you. Take each line one at a time an you'll see there very little that is new here from what we've already covered. The statements that are new we'll get to shortly. Source code such as this around 250 lines long is nothing when compared to a full featured game, of which many I've written in QB64, at around 3000 lines of code or more. If you stick with programming you'll be busting out code this length and longer on a regular basis.

The ASC and CHR$ Statements

The CHR$ statement is used to print any value from 0 to 255 that corresponds to a character within the ASCII table. Typically CHR$ is used to print characters that are not accessible through the keyboard through standard means. One example would be playing card suits that are in the ASCII table.

PRINT CHR$(3) ' ♥ heart symbol
PRINT CHR$(4) ' ♦ diamond symbol
PRINT CHR$(5) ' ♣ club symbol
PRINT CHR$(6) ' ♠ spade symbol

The ASC statement does just the opposite and returns the ASCII numeric value of a character passed to it.

PRINT ASC("A") ' 65 printed to the screen
PRINT ASC(" ") ' 32 printer to the screen

This example program shows how the ASC and CHR$ statements can be used together to identify keystrokes. Save the code as CHR_ASC.BAS when finished typing it in.

The STRING$ and SPACE$ Statements

When you need a lot of the same character in a row the STRING$ statement has you covered. Simply supply STRING$ with a numeric value and a character like so:

PRINT STRIN$(80, "*")  ' 80 asterisks will be printed to the screen

You can also supply STRING$ with the ASCII numeric value of a character.

PRINT STRIN$(80, 42) ' 80 asterisks will be printed to the screen

The STRING$  statement comes in handy when building text screen boxes by using the extended ASCII characters provided to do so. Type in the following example and save it as ASCIIBoxes.BAS when complete.

Figure 5 - Old School ASCII Boxes

The SPACE$ statement is used to generate spaces of a requested length.

PRINT SPACE$(80) ' 80 spaces printed to the screen

The SWAP Statement

The SWAP statement is used to switch values between two numeric or string values. The variables to be swapped must be of the same type. The following example shows the SWAP statement in action. Save the code as SwapDemo.BAS when completed.

Figure 6 - Variable Swapping

A Quick String Manipulation Demo

Here is a sample program that uses string manipulation to create a hidden password function. Save the code as HiddenPassword.BAS when finished typing it in.

Figure 7 - Don't Peek!

Your Turn

Create a program that scans a user supplied sentence and counts the individual letters found within the sentence. Figure 8 below shows how the program should execute.

Figure 8 - Counting Letters

- Each letter in the sentence should be counted regardless of being upper or lower case.
- No graphics screen is needed. Program should run in standard text screen.
- Save the program as LetterCount.BAS when finished.

Click here to see the solution.


New commands introduced in this task:


New concepts introduced in this task:


Commands learned in Task 10:


Concepts learned in Task 10:

one dimensional array
two dimensional array
three dimensional array
Dynamic Array
Static Array

Commands learned in Task 9:


Concepts learned in Task 9:

ASCII chart

Commands learned in Task 8:


Concepts learned in Task 8:

local variables
global variables
Pythagorean Theorem

Commands learned in Task 7:


Concepts learned in Task 7:

aspect ratio

Commands learned in Task 6:

DO...LOOP (and variations)

Concepts learned in Task 6:

frame rate
controlled loops
conditional loops

Commands learned in Task 5:

colon ( : )

Concepts learned in Task 5:

relational operators
order of operations

Commands learned in Task 4:

REM or '

Concepts learned in Task 4:

type declarations
literal strings
long integers
single precision
double precision
null strings
reserved words
operators ( +, -, *, / )

Commands learned in Task 3:


Concepts learned in Task 3:

literal string
syntax error