Strings in TCL

There are two kinds of strings in TCL, constant strings and variable strings. Constant strings are the literal strings enclosed in double quotes. They cannot be changed by the script. String variables are just that - they are variables and can be changed like any other variable.

Constant strings (aka String Literals)

A TCL script can display messages to the operator, for example using the $Draw Message action, which might look like this:

Actions:
... DO $Draw Message (1,1,1)="Hello, world"

Here, the message is fixed to the string types in the script. The timing of when and where it is displayed can be controlled by the script, but the content of the message is fixed.

It is possible to enclose variables inside a string literal (the text in between two double quotes) by using @<name>

Variables: x
Actions:
... DO x=17, $Draw Message (1,1,1)="Variable x=@x"

This will display the text: Variable x=17

So in a way our 'constant' string is now a 'variable', but only in a fixed manner. The value of the variable is inserted into the string at the time that the string is displayed.

The variable name after the '@' can only be a simple variable name and that name must be separated from what comes after it, so it is more flexible to use @{<expression>}

Variables: STRUCT (a,b,c)=(t[5])
Actions:
... DO x=17, $Draw Message (1,1,1)="Variable t[3].a=@{t[3].a}"

Using the clamps (or curly brackets) you can use arrays, elements of structures, method calls and even simple expressions, such as:

Variables:
        wd[6], a,
        STRUCT (aa,b,c)=(s[3])
Strings:
        sw [6]
Actions:
... DO a=1, wd[3]=2, s[1].aa=3, sw[3]="abcd"
        $Draw Message (1,1,1)="string @{a}a @{wd[3]} @{s[1].aa} @{sw[3].strlen ()} @{wd[3]+3} string"

This displays the message: string 1a 2 3 4 5 string

String variables

Most variable data in TCL are simple numbers, but TCL can also support simple string variables. For example:

Strings: s1
Actions:
... DO s1="Hello, world", $Draw Message (1,1,1)=s1

Sets string variable 's1' to Hello, world and then displays that variable at position 1,1 in CTC1.

This example copied a string literal into a string variable. Note that string variables (strings declared in the 'Strings:' header) are variables - they can be changed. String literals copied into string variables can contain variables as illustrated above and the value of the variable is taken at the time that the string literal is copied to the variable.

You can assign either a string variable or a string literal to a string variable. You can compare any combination of string variables and literals using the regular comparison operators: =, <>, <, <=, >, >=.

String variables are objects and not plain variables. This means that they have methods (called subroutines or functions in some languages).

You can combine strings together by appending one to another:

Strings: s1, s2
Actions:
... DO s1="Hello, ", s2="world", s1.append (s2),
       $Draw Message (1,1,1)=s1

String s2 is appended to s1 making the string "Hello, world" once more. In fact you can append several strings and numbers to a string, like this:

Variables: x
Strings: s1, s2
Actions:
... DO x=5, s1="Result", s1.append (" x=", x),
... DO x=17, $Draw Message (1,1,1)="Variable x=@x"

The first statement (starting x=5) assigns a string literal to a string variable, then appends another literal and a numeric variable both together, yielding: "Result x=5". The second line has a numeric variable embedded in the string literal and yields: "Variable x=17". In the first the value inserted into the string is the value that existed when the string was build using the append method, and in the second it is the value in x when the draw message is executed.

Pointers to string variables may be stored in regular variables and operate in the same manner as any other pointers.

The methods available to string variables is currently as follows:

x = s1.strlen ()

x = s1.strlen (word)

Returns the integer length of the string, as measured in characters.

Returns the length of the specified word within the string.

append

s1.append (number, "string", number)

Appends each parameter in turn to the string variable. The parameters can be string literals, string variables or regular variables (including sensors, controls etc).

Returns a pointer to the string appended to (not normally used).

appendChar

s1.appendChar (number)

Appends each numeric parameter as a single character using the value as the unicode codepoint.

String parameters are appended as strings.

appendHex (value, number of digits , base)

Append the numeric value parameter as a hexadecimal number, or other base if specified.

insert

s1.insert (insertAt, params)

Inserts a list of parameters (as per append) at the character index specified by numeric parameter 'insertAt'. If 'insertAt' is zero then the parameters are inserted at the start of the string.

Returns a pointer to the string appended to (not normally used).

replace (start, end, params)

p = s1.replace (3, 5, "replacement")

Replaces characters from character position 'start' (0 is first character) upto but NOT including character 'end' with the (possibly empty) list of parameters that follow.

Returns a pointer to the string appended to (not normally used).

replaceInWord (word, start, end, params)

As for replace () but actions part of a word instead of the whole string.

substring (start, end)

substring (word number)

substring (word, start, end)

s2 = s1.substring (1, 4)

Extracts the characters from character position 'start' upto but excluding 'end'. Puts this sub-string in a temporary string and returns a pointer to the temporary string. Two temporary strings are used alternately so it is best to store the result into another string variable, or use it immediately.

parse (word, start, end, default)

x = s1.parse ()

x = s1.parse (word number)

x = s1.parse (,start, end)

x = s1.parse (word, start, end)

x = s1.parse (,,,default)

Returns the integer value stored in the string. The string "56" would return 56. No non-numeric characters are allowed in the string.

The whole string, a single word, part of the string or part of a word can be parsed in this way.

If the word number is omitted the whole string is used. Start and end default to the start and end of the word or whole string as appropriate. If default is supplied then it is returned if no valid number can be found.

Unwanted parameters are skipped by missing them out, but keeping the commas.

parseHex (word, start, end, default)

Returns the integer value stored in the string as a hex number. See parse () above for parameter formats.

s1.trim ()

Removes leading and trailing blanks from a string. Useful if a string is to be used as a filename.

indexof (string)

indexof (start, string)

indexOf (word, start, string)

x = s1.indexof ("bill")

Returns the character position of the first occurrence of the string that is the last parameter in this call. If a start parameter is supplied it sets the position where searching commences (within the whole string or just one word as appropriate).

x = wordStarting (string)

Return the word number of the first word that starts with the given string.

x = wordMatching (string)

Return the word number of the first word that exactly matches string.

x = getWord (word)

Return a copy of the specified word from the string.

setWord (word, string)

Replace the specified word with the string.

x=charAt (index)

x=charAt (word, index)

Return the specified character in the string (or from a word in the string) as an integer. The value returned is the unicode value of the character, which mostly matches the ASCII code for the same character.

pop ()

pop (index)

pop (word, index)

x = s1.pop ()

Removes a single character from the start of the string and returns it as an integer.

Removes the specified character in the string.

Removes the specified character from a word in the string.

popWord ()

popWord (word)

popWord (separator)

s2 = s1.popWord ()

Removes the first word from the string and returns it, in a temporary string.

Removes the specified word and returns it.

The definition of what separates words can be specified. It is a regular expression defining boundaries between words and defaults to " *" meaning any number of spaces.

clear ()

s1.clear (params)

Empties the string. Same as s1=""

If parameters are given then they are appended after emptying the string. Same as s1.clear (), s1.append (params).

toUpperCase (word, start, end)

toLowerCase (word, start, end)

Same as substring, but returns result in upper case, or lower case as appropriate (in a temporary string).

With no parameters returns whole string converted.

toASCII (word, start, end)

fromASCII (word, start, end)

Convert the string (or word, or part of the string) from unicode to ASCII or back again. This means that characters outside of the basic ASCII range are changed to \u<hex> where <hex> is a four digit hex number. Useful for storing strings containing symbols into a file or database which can only handle ASCII.

wordCount ()

Returns number of words in this string.

str = s1.quoteWords (quote)

str = s1.quoteWords (leftQuote, rightQuote)

Put quote marks around all the words in the string. Possibly useful for splitting a string for a database write, or for some file logging.

Note that a method call can be used as a parameter to another method, so to extract the number from "76 trombones" one could use:

Variables: b

Strings: s1

WHEN ... DO s1="76 trombones", b=s1.substring (0, s1.indexOf (" ")), b=b.parse ()


s1.indexOf (" ") returns the index of the first space in string s1

s1.substring (0, s1.indexOf (" ")) returns the portion of s1 before the first space, ie "76". A pointer to this temporary string is stored in variable b.

The temporary string "76" is then parsed (scanned for a number) and the value 76 returned and stored back into b.

WARNING: All methods of all objects that return strings put the results in one of just TWO temporary string variables and return a pointer to the temporary variable. If you fetch three string results the third will OVERWRITE the first. To prevent such problems either use the results immediately or save them into string variables (not just regular variables).

Last updated 5 August 2017.

© Howard Amos 2008-2017