Updated 2012-12-01 05:00:51 by RLE
string length string

Returns a decimal string giving the number of characters in string. Note that this is not necessarily the same as the number of bytes used to store the string. If the object is a ByteArray object (such as those returned from reading a binary encoded channel), then this will return the actual byte length of the object.

Subcommand of string, returns the length of its argument in (Unicode) characters, which may differ from the result of string bytelength on the same string (because of the UTF-8 implementation).

If you want to use a name familiar from C, you might do this:
 interp alias {} strlen {} string length

2003-10-17 in the Tcl chatroom, some of us played around with silly pure-Tcl implementations of string length:
 proc strlen s {
    set n 0
    foreach char [split $s ""] {incr n}
    set n
 } ;# RS

 proc strlen s {llength [split $s ""]} ;# AM

 proc strlen string {
    regsub -all . $string +1 string
    expr 0$string
 } ;# MS

jcw - does the above perhaps need a -all? Also, why not simply:
   return [regexp -all . $string]

MS indeed; corrected now. In the why not simply department, why not
   regexp -all . $string

or using aliases
   interp alias {} strlen {} regexp -all . ;# MS

 proc strlen string {expr 0[regsub -all . $string +1]} ;# dkf

The functional way:
 proc strlen {s} {
   expr {[regexp {.(.*)} $s - s] ? (1+[strlen $s]) : 0}
 } ;# EB

ulis, A recursive way:
  proc strlen {string} \
  {
    if {$string == ""} { return 0 } \
    else { expr [strlen [string range $string 1 end]] + 1 }
  }

And the classical iterative way:
  proc strlen {string} \
  {
    set n 0
    while {$string != ""} { set string [string range $string 1 end]; incr n }
    return $n
  }

Powers of ten (sorrily, this works only for short strings):
 proc strlen s {
   expr round(log10(1.[regsub -all . $s *10]))
 } ;# RS

At times, people ask which is better for determining whether a string is empty (null):
 [string equal x x$str]
 [string equal "" $str]
 ![string compare "" $b]
 [string length $str] == 0
 ![string length $str]
 $str eq ""

The string length or string equal will be a bit quicker, as they will look to see if the strings are of equal size first.

Negative-length strings: A bug (SF 230589) in regexp produces incredible consequences:
 % regexp {[ ]*(^|[^@])@} "x@" m; puts [string length $m]
 -109537

Numbers vary by platform, the above was 8.4.1 on Solaris. (CMcC via RS)


See also edit