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.
strcan never exist alone. It is always used as&str(orBox<str>or*str, but in your case those shouldn't matter).&strdoes not own any data. It is merely a reference to (parts of) anotherString.Stringactually 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
Stringto a&str. Somewhere the data has to be stored, and&strdoesn'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
Stringinstead.
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 = " 