Tcl Part I · Module 5 · Strings
string length, and What a Character Is
Measuring a string is the simplest thing in this module, and it takes one line. The chapter exists for the question underneath it: what exactly is being counted? Tcl counts characters, not bytes, and for plain English text those are the same number so the distinction never surfaces. The moment an accented letter or any non-English text arrives they stop being the same, and knowing which one you have is the difference between a correct column width and a misaligned report.
Foundation9 min readTclPart IStringsLengthEncoding
Part I · Module 5 · Chapter 5.2 · string length, and What a Character Is
1. The Command
puts [string length "summary"]
puts [string length ""]
puts [string length "a b c"]7
0
5Seven characters, zero, and five — the spaces count, because they are characters in the string.
The empty string is 0, which is worth seeing because it is the basis of the most common use of this command.
2. The Most Common Use: Is It Empty?
set name ""
if {[string length $name] == 0} {
puts "no name supplied"
}no name suppliedThat works, and there is a shorter way that reads better:
set name ""
if {$name eq ""} {
puts "no name supplied"
}no name suppliedBoth are correct. eq says "is it the empty string" directly, which is what you meant — Chapter 4.4. Use string length when you need the number for something else, not merely to compare it with zero.
3. Characters, Not Bytes
Now the part worth the chapter:
set word "café"
puts "characters: [string length $word]"
puts "bytes as UTF-8: [string length [encoding convertto utf-8 $word]]"characters: 4
bytes as UTF-8: 5Four characters — c, a, f, é. Five bytes, because é needs two of them in UTF-8.
Tcl counts characters. For "summary" the two numbers are identical, which is why the distinction stays invisible in most scripts. It becomes visible the first time a name, a comment, or a field contains anything outside plain ASCII.
4. Which One Do You Want?
Almost always characters, which is what you already get:
- Lining up a column — characters. A report column is a count of visible positions.
- Truncating a name to fit — characters. Cutting mid-character would corrupt the text.
- Validating a maximum length — usually characters, unless a specification says bytes.
- Sizing a file or a buffer — bytes. This is the exception.
For the exception, convert and then measure, as §3 did:
string length [encoding convertto utf-8 $text]5. Length of Things That Are Not Obviously Strings
Every Tcl value has a string representation — Chapter 3.1 — so string length works on anything:
puts "number: [string length 12345]"
puts "real: [string length 3.14]"
puts "list: [string length {a b c}]"
puts "result: [string length [expr {2 ** 20}]]"number: 5
real: 4
list: 5
result: 7The list case is the one to notice. {a b c} as text is five characters — a, space, b, space, c. If you wanted the number of elements you want llength, which is Module 6:
set items {a b c}
puts "string length: [string length $items]"
puts "llength: [llength $items]"string length: 5
llength: 3Two different questions about the same value, which is Chapter 3.1 §4 exactly.
6. A Practical Use: Padding a Column
set names {clk reset data_valid rx}
foreach n $names {
set pad [string repeat "." [expr {14 - [string length $n]}]]
puts "$n$pad ok"
}clk........... ok
reset......... ok
data_valid.... ok
rx............ okThe padding is computed from the length, so the column lines up regardless of the name.
That said, format does this directly and handles the arithmetic for you — Chapter 5.11:
foreach n {clk reset data_valid rx} {
puts [format "%-14s ok" $n]
}clk ok
reset ok
data_valid ok
rx okUse format for alignment. Use string length when you need the number itself.
7. Common Mistakes
Comparing the length with zero to test for empty. $s eq "" says it better. §2.
Calling it on an unset variable. That is an error, not 0. §2.
Using it to count list elements. That is llength. §5.
Assuming characters equal bytes. True for ASCII only. §3.
Using bytelength for on-disk size. §4.
Computing padding by hand when format would do it. §6.
8. Exercises
Exercise 1 — three lengths. Measure "hello", "", and "a b" (two spaces). Predict each first.
Exercise 2 — characters versus bytes. Measure a word containing an accented letter both ways, as in §3. Then try a word with two accented letters and predict the byte count before running it.
Exercise 3 — two questions. For the value {red green blue}, produce both the character count and the element count. Say in one sentence why they differ.
Exercise 4 — the empty test, three ways. Test whether a variable is empty using string length, using eq, and using string equal. Which would you keep, and why?
Exercise 5 — build a ruler. Print a line of 50 dashes using string repeat, then a line that is exactly as long as a name you choose. Use string length for the second.
Exercise 6 — align without format. Line up three names in a 12-character column using only string length and string repeat. Then do it again with format and compare the two versions.
9. Remember
string length $textcounts characters. The empty string is 0.- To test for empty, prefer
$s eq ""— it says what you mean. - On an unset variable it is an error, not 0.
- Characters are not bytes once text leaves ASCII.
"café"is 4 characters and 5 bytes. - Count characters unless you are sizing storage, and convert with
encoding convertto utf-8when you are. string bytelengthis not the on-disk size.- It works on any value, because every value has a string representation — but
llengthis what counts list elements. - For alignment,
formatis the better tool.
Next: getting at individual characters and spans.
Where this fits
Part of the Tcl curriculum.
