Skip to content

str::split_at

str methods · Strings

Level: reference · for working programmers

One line: Cuts the string in two at a byte offset, returning both halves — and panics if the offset is not a character boundary.

pub const fn split_at(&self, mid: usize) -> (&str, &str)

Stable since 1.4.0. Usable in a const context.

"hello".split_at(2) is ("he", "llo"). The argument is a byte index, not a character count, and the two failure modes are the same as slicing:

  • out of range — mid > len()
  • inside a character — "héllo".split_at(2) panics, because byte 2 is the second half of é

Both are run-time panics, not compile errors, which makes this one of the few string operations that can bring a program down on data it has never seen. split_at_checked is the same cut returning Option, and is the better default in any code handling text you did not write.

split_at(0) and split_at(len()) are legal and give an empty half.

Example

str_split_at.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    println!("{:?}", "hello".split_at(2));
    println!("{:?}", "hello".split_at(0));
    println!("{:?}", "hello".split_at(5));

    // Byte offsets: 'é' occupies bytes 1 and 2, so only 1 and 3 are legal.
    let s = "héllo";
    for mid in 0..=s.len() {
        let ok = s.is_char_boundary(mid);
        println!("mid {mid} boundary={ok:<5} {:?}", if ok { Some(s.split_at(mid)) } else { None });
    }

    // The safe form, which reports the refusal instead of panicking.
    println!("{:?}", s.split_at_checked(2));
    println!("{:?}", s.split_at_checked(99));
}

Verified output of str_split_at.rs — regenerated by tools/run_examples.py, never hand-typed.

("he", "llo")
("", "hello")
("hello", "")
mid 0 boundary=true  Some(("", "héllo"))
mid 1 boundary=true  Some(("h", "éllo"))
mid 2 boundary=false None
mid 3 boundary=true  Some(("hé", "llo"))
mid 4 boundary=true  Some(("hél", "lo"))
mid 5 boundary=true  Some(("héll", "o"))
mid 6 boundary=true  Some(("héllo", ""))
None
None

See also

str::split_at in the standard library ↗

Po polsku

split_at dostaje offset w bajtach, a nie numer znaku, i dla polskiego tekstu to różnica jak najbardziej praktyczna: w UTF-8 każde ą, ć, ę, ł, ń, ó, ś, ź, ż zajmuje po dwa bajty, więc w "żółw" (7 bajtów) legalne cięcia to 0, 2, 4, 6 i 7 — a split_at(3) ląduje w środku ó i program panikuje, dokładnie tak jak "héllo".split_at(2) z przykładu wyżej, gdzie tabelka pokazuje mid 2 boundary=false. To nie jest błąd kompilacji, tylko panika w czasie działania, więc taki kod przechodzi wszystkie testy na danych ASCII i wywraca się dopiero na tekście od użytkownika. W kodzie dotykającym cudzego tekstu domyślnie sięgaj więc po split_at_checked (zamiast panikować, zwraca None) albo sprawdź offset przez is_char_boundary; skrajne cięcia split_at(0) i split_at(len()) są legalne i dają pustą połówkę.

Szukaj po polsku: polskie znaki zajmują dwa bajty · granica znaku w łańcuchu znaków · rust byte index is not a char boundary · rust split_at panic utf8