3

According to my understanding, a string in V is wrapped around a byte array encoded as UTF-8. That way, iterating over all string elements returns the bytes:

fn main() {
    s := 'a string with äöü (umlauts)'
    println(s)
    for i := 0; i < s.len; i++ {
        print('-')
    }
    println('')
}

resulting in (note the longer underlining):

a string with äöü (umlauts)
------------------------------

How to get the length of the string in characters/runes? How to iterate over all characters/runes instead of bytes?

Thomas S.
  • 5,804
  • 5
  • 37
  • 72

2 Answers2

2

It looks like one needs to use the encoding.utf8 module:

import encoding.utf8

fn main() {
    s := 'a string with äöü (umlauts)'
    println(s)
    for i := 0; i < utf8.len(s); i++ {
        print('-')
    }
    println('')
}
Thomas S.
  • 5,804
  • 5
  • 37
  • 72
  • 2
    The `rune` type is in the works right now. In the future this should be doable without importing a separate encoding module, but still WIP at this point unforunately. – Major Nov 28 '20 at 05:39
2

You can call .runes() method on strings. This returns array of runes.

The following code demonstrates converting string to array of runes and then prints its type and lenght.

fn runes_demo(s string) {
    println(s)
    // Iterate over runes of string
    for _ in s.runes() {
        print('_')
    }
    println('')
    println('Return type of runes(): ${typeof(s.runes()).name}')
    println('Length of string in runes: $s.runes().len')
    println('')
}

fn main() {
    s := 'a string with äöü (umlauts)'
    runes_demo(s)
    t := 'hello there!'
    runes_demo(t)
}

This outputs the following:

a string with äöü (umlauts)
___________________________
Return type of runes(): []rune
Length of string in runes: 27

hello there!
____________
Return type of runes(): []rune
Length of string in runes: 12


navule
  • 3,212
  • 2
  • 36
  • 54
  • To get back from an array of `rune` to a `string`, use the `string()` method. There's lots of similarly named functions and fields, so it may not be obvious this is the right one. To be clear: `assert s.runes().string() == s` – Heath Raftery Mar 04 '23 at 23:33