Skip to content

String Sample

Adapted from the archived Vala String Sample page.

See Language Features and Introductory Samples for the full set.

vala
void println (string str) {
    stdout.printf ("%s\n", str);
}

void main () {

    /* Strings are of data type 'string' and can be concatenated with the plus
     * operator resulting in a new string:
     */
    string a = "Concatenated ";
    string b = "string";
    string c = a + b;
    println (c);

    /* If you want to have a mutable string you should use StringBuilder.
     * With its help you are able to build strings ad libitum by prepending,
     * appending, inserting or removing parts. It's faster than multiple
     * concatenations. In order to obtain the final product you access the
     * field '.str'.
     */
    var builder = new StringBuilder ();
    builder.append ("built ");
    builder.prepend ("String ");
    builder.append ("StringBuilder");
    builder.append_unichar ('.');
    builder.insert (13, "by ");
    println (builder.str); // => "String built by StringBuilder."

    /* You can create a new string according to a format string by calling the
     * method 'printf' on it. Format strings follow the usual rules, known from
     * C and similar programming languages.
     */
    string formatted = "PI %s equals %g.".printf ("approximately", Math.PI);
    println (formatted);

    /* Strings prefixed with '@' are string templates. They can evaluate
     * embedded variables and expressions prefixed with '$'.
     * Since Vala 0.7.8.
     */
    string name = "Dave";
    println (@"Good morning, $name!");
    println (@"4 + 3 = $(4 + 3)");

    /* The equality operator compares the content of two strings, contrary to
     * Java's behaviour which in this case would check for referential equality.
     */
    a = "foo";
    b = "foo";
    if (a == b) {
        println ("String == operator compares content, not reference.");
    } else {
        assert_not_reached ();
    }

    /* You can compare strings in lexicographical order with the < and > operators: */
    if ("blue" < "red" && "orange" > "green") {
        println ("blue is less than red and orange is greater than green");
    }

    /* Verbatim strings: escape sequences are not interpreted, line breaks are
     * preserved, and quotes need not be escaped. Indentation after a line break
     * is part of the string.
     */
    string verbatim = """This is a so-called "verbatim string".
Verbatim strings don't process escape sequences, such as \n, \t, \\, etc.
They may contain quotes and may span multiple lines.""";
    println (verbatim);

    // Switch statement
    string pl = "vala";
    switch (pl) {
    case "java":
        assert_not_reached ();
    case "vala":
        println ("Switch statement works fine with strings.");
        break;
    case "ruby":
        assert_not_reached ();
    }

    /* You can apply various operations on strings. Here's a small selection: */
    println ("from lower case to upper case".up ());
    println ("reversed string".reverse ());
    println ("...substring...".substring (3, 9));

    /* The 'in' keyword is syntactic sugar for checking if one string contains
     * another string. The following expression is identical to
     * "swordfish".contains ("word")
     */
    if ("word" in "swordfish") {
        println ("word is a part of swordfish");
    }

    // Regular expressions
    try {
        var regex = new Regex ("(jaguar|tiger|leopard)");
        string animals = "wolf, tiger, eagle, jaguar, leopard, bear";
        println (regex.replace (animals, -1, 0, "kitty"));
    } catch (RegexError e) {
        warning ("%s", e.message);
    }
}

Compile and run

shell
valac string-sample.vala
./string-sample

String length and UTF-8

Before Vala 0.11, .length was the number of Unicode code points and .size() was the length in bytes. Starting with Vala 0.11, .length is the length in bytes and indexing is byte-based. Strings remain UTF-8; indices, offsets, and lengths use UTF-8 code units (bytes), which matches many other string APIs and helps performance while still supporting Unicode text.

vala
string dessert = "crème brûlée";
assert (dessert.length == 15);
uint8 a_byte = dessert[3];
assert (a_byte == 0xA8);

C# and Java

Java’s String.length and .NET’s String.Length count UTF-16 code units (often two bytes per unit). Vala counts UTF-8 code units (bytes). A string can therefore have different numeric “lengths” across these platforms for the same text.

UTF-8 character iteration

Because UTF-8 is variable-length, characters are not random-access by index. Avoid inefficient patterns such as:

vala
string str = "吃饭了";
for (int i = 0; i < str.char_count (); i++) {
    str.get_char (str.index_of_nth_char (i));
}

Prefer get_next_char, which advances a byte offset and yields each unichar:

vala
unichar c;
for (int i = 0; str.get_next_char (ref i, out c);) {
    stdout.printf ("%d, %s\n", i, c.to_string ());
}