if i want to get the next character from alphabets how to do it. let's suppose i have string "hello" and i want to move each character by 4 position "lipps". how to do it
Here's a sketch of a possible approach:
fn add1_char(c: char) -> char {
std::char::from_u32(c as u32 + 1).unwrap_or(c)
}
fn add1_str(s: &str) -> String {
s.chars().map(add1_char).collect()
}
If I understand @Harry's intent correctly, he will probably also want to add some range checks (is this an alphabetic character ?) and some modulo-based wraparound (to handle the end of the alphabet) to this sketch.
Just to have mentioned it: depending on what it is that you want you might be better off using the unicode_segmentation
crate, which provides an iterator that yields graphemes rather than chars.
This distinction doesn't matter when you just want byte
s or char
s, but is very important when working with non-ascii (i.e. Unicode) texts (e.g. in UTF-8).
Here is simple example satisfying your requirements:
fn move_shift(data: &String, shift: usize) -> String {
data.chars().map(|c| (c as u8 + shift as u8) as char).collect::<String>()
}
yes.
If your alphabet is small Latin letters from a to z, then this code will work:
#[derive(Debug)]
struct MyError;
fn shift(input: &str, shift: i8) -> Result<String, MyError> {
let mut buf = Vec::with_capacity(input.len());
for byte in input.bytes() {
match byte {
b'a'..=b'z' => {
let mut val = byte as i16 + shift as i16;
if val > b'z' as i16 || val < b'a' as i16 {
val -= b'a' as i16;
val = if val >= 0 {
(val % (b'z' as i16)) + b'a' as i16
} else {
1 + b'z' as i16 + (val % (b'z' as i16))
}
}
buf.push(val as u8);
}
_ => Err(MyError)?,
}
}
let out = String::from_utf8(buf)
.expect("we are sure that all bytes fall into ASCII range");
Ok(out)
}
fn main() {
println!("{:?}", shift("hello", 4).unwrap());
println!("{:?}", shift("abcdef", -3).unwrap());
}
It prints "lipps" and "xyzabc". It can be done without allocating additionall string, though code will be a bit more complex.