Home > Enterprise >  How to build a str in Rust
How to build a str in Rust

Time:12-02

Suppose I have a char in the variable c and a positive int in the variable n. I want to build the str containing c occurring n times. How can I do it?

I tried building it as a String, and maybe I just got dizzy trying to read the documentation on strings, but I couldn't see how to convert it to a str. But then if I'm trying to just build it as a str directly then I couldn't see how to do that either.

For context, here is the full function I'm trying to implement. It takes a string and finds the longest sequence of consecutive characters (and breaks ties by taking the first that occurs).

pub fn longest_sequence(s: &str) -> Option<&str> {
    if s.len() == 0 { return None; }
    let mut current_c = s.as_bytes()[0] as char;
    let mut greatest_c = s.as_bytes()[0] as char;
    let mut current_num = 0;
    let mut greatest_num = 0;
    for ch in s.chars() {
        if current_c == ch {
            current_num  = 1;
            if current_num > greatest_num {
                greatest_num = current_num;
                greatest_c = current_c;
            }
        } else {
            current_num = 1;
            current_c = ch;
        }
    }
    // Now build the output str ...
}

CodePudding user response:

I think there are a couple of misconceptions about str vs String.

  • str can never exist alone. It is always used as &str (or Box<str> or *str, but in your case those shouldn't matter).
  • &str does not own any data. It is merely a reference to (parts of) another String.
  • String actually holds data.
  • So when you want to return data, use String; if you want to reference existing data, return &str.
  • There is no way to convert a local String to a &str. Somewhere the data has to be stored, and &str doesn't store it. (for completeness sake: Yes you could leak it, but that would create a permanent string in memory that will never go away again)

So in your case there are two ways:

  • Reference the input &str, because somewhere its data is already stored.
  • Return a String instead.

As a side note: do not do s.as_bytes()[0] as char, as it will not work with UTF8-strings. Rust strings are defined as UTF8.

Here is one possible solution:

pub fn longest_sequence(s: &str) -> Option<&str> {
    let mut current_c = s.chars().next()?;
    let mut current_start = 0;
    let mut current_len = 0;
    let mut greatest: &str = "";
    let mut greatest_len = 0;
    for (pos, ch) in s.char_indices() {
        if current_c == ch {
            current_len  = 1;
        } else {
            if greatest_len < current_len {
                greatest = &s[current_start..pos];
                greatest_len = current_len;
            }

            current_len = 1;
            current_c = ch;
            current_start = pos;
        }
    }

    if greatest_len < current_len {
        greatest = &s[current_start..];
    }

    Some(greatest)
}

pub fn main() {
    let s = "           
  • Related