CellSpeak Strings
The basic type for strings in CellSpeak is the array of bytes.
The type zt, for zero-terminated is an intermediate type derived from the type byte[] and is defined in the platform package.
Also there a number of methods and functions are defined to handle zero-terminated byte strings.
Based on that zero-terminated type several other string types are defined, like
ascii, ansi and utf8, that take into account the encoding of the characters within a zero-terminated string.
The following examples are fairly straightforward and show how to work with strings in CellSpeak.
As for all arrays, strings that are assigned to are allocated automatically. Strings that are not part of the permanent data of a cell, are allocated on scratch-pad memory,
which is reset automatically after the execution of each message handler. So in most of the cases allocation/de-allocation can simply be dispensed with.
(1) We do not have to allocate space for the string firs - we can simply assign.
(2) Expressions between [ and ] in a string are replaced by their stringified values.
(3) The string is one byte longer because of the newline character: \n = 1 byte
(4) Strings can span several lines. Leading white space is included in the string.
(5) You can use the special character /- to indicate that leading white space should not be included.
This string will be alligned to the left of the window it is printed in.
(6) The original string-value in a is lost here. But we do not have to de-allocate and reallocate.
a is a variable that is local to the constructor and is maintained on the scratchpad memory.
When exiting the constructor, all scratchpad memory is released.
(7) In stead of is you can also use the familiar == sign.
The comparison function for strings is a byte-wise comparison.
(8) We can use slices to assign to parts of an array.
i:1+3 will assign to four bytes in the array: i, i+1, i+2, i+3
(9) The string is not copied because we use a reference assignment.
Note that even if we re-assign the original string, this string will remain valid because it is allocated on the scratchpad memory.
If we change the original string, the changes will also be visible in this string.
03 CellSpeak Strings.celsrc
use Windows, Math, Strings, Editor
group StringHandling
design Demonstrator is
cell Window = create MenuWindow("String test")
constructor is
Window <- print("\nSome tests with strings")
Window <- print("\n\n***Test1: basics\n")
(1) ansi a = "Short string"
(2) Window <- print("\nThe string \"[a]\" is [a.len()] bytes long")
(3) a = "\nShort string"
Window <- print("\nThe string \"[a]\" is [a.len()] bytes long - the new line character was added at the front")
Window <- print("\nThe string \"[a]\" is [a.lenz()] bytes long - if we include the terminating 0 byte.")
Window <- print("\n\n***Test2: multi-line strings\n")
(4) ansi b = "
This is a string
which spans several lines
and is alligned with the first line.
Leading white space remains."
(5) ansi b2 = "\n\-This is also a string
which spans several lines
and is alligned with the first line.
But here, leading white space is removed."
Window <- print(b)
Window <- print(b2)
Window <- print("\n\nThe strings are [b.len()] and [b2.len()] bytes long")
Window <- print("\n\n***Test3: re-assign a constant string to an existing string\n")
(6) a = "\nThis is a slightly longer string then before."
Window <- print(a)
a = "first"
b = "second"
Window <- print("\nNow a = '[a]' and b = '[b]' ")
a,b = b,a
Window <- print("\nSwapped a and b -> now a = '[a]' and b = '[b]' ")
a,b := b,a
Window <- print("\nSwapped a and b again -> now a = '[a]' and b = '[b]' ")
Window <- print("\n\n***Test4: string comparisons: 0 means equal, negative earlier and positive later in the alphabet : a < b\n")
a = "abcdef"
b = "abcdghij"
Window <- print("\ncompare([a],[b]) returns [compare(a,b)]")
Window <- print("\ncompare([b],[a]) returns [compare(b,a)]")
Window <- print("\ncompare([b],[b]) returns [compare(b,b)]")
Window <- print("\ncompare([a],[a]) returns [compare(a,a)]")
(7) if a is b then
Window <- print("\n'[a]' and '[b]' are equal")
else
Window <- print("\n'[a]' and '[b]' are not equal")
end
a is a ? Window <- print("\n'[a]' is always equal to itself !")
a > b ? Window <- print("\n'[a]' > '[b]'") : Window<-print("\n'[b]' > '[a]'")
a is "abcdef" ? Window <- print("\n'[a]' and 'abcdef' are indeed equal")
if a is "abcdef" then
Window <- print("\n'[a]' and 'abcdef' are equal")
else
Window <- print("\n'[a]' and 'abcdef' are not equal")
end
Window <- print("\n\n***Test5: Modifying a string\n")
a[3] = 0x58
a[4] = 0x'Y'
Window <- print("\na\[3] and a\[4] - the fourth and the fifth character - are changed in '[a]' ")
a = "Kathy and Peter lived in Spain for 2 years."
Window <- print("\nString: '[a]'")
a.upper()
Window <- print("\nUpper case: '[a]'")
a.lower()
Window <- print("\nLower case: '[a]'")
a = "Bob and Alice share the same password :'1234' !"
ansi c,d
Window <- print("\nString: '[a]'\nUpper case: '[ c = upper(a) ]'\nLower case: '[ d = lower(a) ]'")
var i = a.find("1234")
(8) a[i:i+3] = "abcd"
Window <- print("\n[a] - much better now.")
a = "Neil Armstrong was the first man on the moon."
Window <- print("\nFound 'A' at position [a.find(0x41)] in '[a]'")
Window <- print("\nFound 'first' at position [a.find(\"first\")] in '[a]'.")
Window <- print("\n\n***Test6: Appending strings\n")
ansi Intro = "My name is"
ansi Name = "Ozymandias"
ansi Occupation = "king of kings"
ansi Motto = "look on my works, ye Mighty, and despair!"
ansi First = "[Intro] [Name], [Occupation], [Motto]"
Window <- print("\nFirst method (formatted string): [First]")
ansi Second
Second.append(Intro)
Second.append(" ")
Second.append(Name)
Second.append(", ")
Second.append(Occupation)
Second.append(", ")
Second.append(Motto)
Window <- print("\nSecond method (append method): [Second]")
Second = ""
Second.append(Intro).append(" ").append(Name).append(", ").append(Occupation).append(", ").append(Motto)
Window <- print("\nSecond method (append chain): [Second]")
ansi Third = ""
Third = Intro + " " + Name + ", " + Occupation + ", " + Motto
Window <- print("\nThird method (append operator): [Third]")
var Il = Intro.len()
var Nl = Name.len()
var Ol = Occupation.len()
var Ml = Motto.len()
var n = 0
ansi[ Il + Nl + Ol + Ml + 6 ] Fourth
Fourth = Intro
Fourth[n+=Il:] = " "
Fourth[n+=1:] = Name
Fourth[n+=Nl:]= ", "
Fourth[n+=2:] = Occupation
Fourth[n+=Ol:] = ", "
Fourth[n+=2:] = Motto
Window <- print("\nFourth method (array slices): [Fourth]")
Window <- print("\n\n***Test7: Unicode\n")
utf8 u1 = "\nText using uncicode UTF-8 encoding."
Window <- print(u1)
utf8 Greek = "\nGreek alphabet: "
for i=0 to 24 do
Greek.append(0x000003b1 + i)
end
Window <- print(Greek)
utf8 Math = "\nMath symbols: "
for i=0 to 0x2F do
Math.append(0x00002200 + i)
end
Window <- print(Math)
utf8 ChineseProverb = "\nWise words indeed: 杀鸡儆猴"
Window <- print(ChineseProverb)
int α, β=2, γ=3
α=β+γ
Window <- print("\nα = β + γ -> [α] = [β] + [γ]")
Window <- print("\n\n***Test8: Substring references\n")
utf8 M7 =
"
The Mercury Seven were the group of seven Mercury astronauts announced by NASA on October 7, 1958.
They are also referred to as the Original Seven or Astronaut Group 1. They piloted the manned
spaceflights of the Mercury program from May 1961 to May 1963. These seven original American
astronauts were Scott Carpenter, Gordon Cooper, John Glenn, Gus Grissom, Wally Schirra,
Alan Shepard, and Deke Slayton.
Members of the group flew on all classes of NASA manned orbital spacecraft of the 20th century —
Mercury, Gemini, Apollo, and the Space Shuttle. Gus Grissom died in 1967, in the Apollo 1 fire.
The others all survived past retirement from service. John Glenn went on to become a U.S. senator,
and flew on the Shuttle 36 years later to become the oldest person to fly in space.
He was the last living member of the class when he died in 2016"
Window <- println(M7)
utf8 Astronauts
var From = M7.find("Scott")
(9) Astronauts := M7[ From: ]
var To = Astronauts.find(0x'.')
Astronauts := Astronauts[:To]
Astronauts[To] = 0x00
Window <- println("\nThe right stuff: [Astronauts]")
end
end