왜 그렇게 복잡합니까?
한 줄씩 나눠 보자
let s1 = "foobar";
UTF-8로 인코딩 된 리터럴 문자열을 만들었습니다 . UTF-8을 사용하면 유니 코드 의 1,114,112 코드 포인트 를 매우 간결한 방식으로 인코딩 할 수 있습니다 . 1963 년에 생성 된 표준 인 ASCII 로 대부분의 문자를 입력하는 세계 지역에서 왔을 때입니다 . UTF-8은 가변 길이입니다. 이는 단일 코드 포인트가 1에서 4 바이트까지 걸릴 수 있음을 의미합니다 . 더 짧은 인코딩은 ASCII 용으로 예약되어 있지만 많은 Kanji는 UTF-8에서 3 바이트를 사용 합니다.
let mut v: Vec<char> = s1.chars().collect();
이것은 char
행위자 의 벡터를 만듭니다 . 문자는 코드 포인트에 직접 매핑되는 32 비트 숫자입니다. ASCII 전용 텍스트로 시작했다면 메모리 요구 사항이 4 배가되었습니다. 만약 우리가 아스트랄 계 의 캐릭터들을 가지고 있다면, 우리는 그다지 많이 사용하지 않았을 것입니다.
v[0] = v[0].to_uppercase().nth(0).unwrap();
이것은 첫 번째 코드 포인트를 잡고 대문자 변형으로 변환하도록 요청합니다. 유감스럽게도 영어로 자란 우리에게는 "소문자"를 "큰 문자"에 대한 간단한 일대일 매핑이 항상있는 것은 아닙니다 . 참고 : 과거에는 한 상자의 글자가 다른 글자 상자보다 위에 있었기 때문에 대문자와 소문자라고 부릅니다 .
이 코드는 코드 포인트에 해당하는 대문자 변형이 없을 때 패닉 상태가됩니다. 실제로 존재하는지 확실하지 않습니다. 또한 코드 포인트에 German과 같이 여러 문자가있는 대문자 변형이있는 경우 의미 상 실패 할 수 있습니다 ß
. ß는 The Real World에서 실제로 대문자로 표기되지 않을 수 있습니다. 이것은 제가 항상 기억하고 검색 할 수있는 유일한 예입니다. 2017년 6월 29일로, 사실, 독일어 맞춤법의 공식 규칙이 이렇게 업데이트되었는지 모두 "ẞ"과 "SS"는 유효한 총액은 !
let s2: String = v.into_iter().collect();
여기서는 문자를 다시 UTF-8로 변환하고 런타임에 메모리를 차지하지 않도록 원래 변수가 상수 메모리에 저장되었으므로이를 저장할 새 할당이 필요합니다.
let s3 = &s2;
그리고 이제 우리는 그것을 참조합니다 String
.
간단한 문제
불행히도 이것은 사실이 아닙니다. 아마도 우리는 세상을 에스페란토 로 바꾸려고 노력해야 할까요?
나는 char::to_uppercase
이미 유니 코드를 제대로 처리한다고 생각한다.
네, 확실히 그러길 바랍니다. 불행히도 모든 경우에 유니 코드만으로는 충분하지 않습니다. 대문자 ( İ )와 소문자 ( i ) 버전 모두에 점이 있는 터키어 I 를 지적 해 주신 huon에게 감사드립니다 . 즉 더 없다,있다 한 편지의 적절한 총액 ; 소스 텍스트 의 로케일 에 따라 다릅니다 .i
모든 데이터 유형 변환이 필요한 이유는 무엇입니까?
작업중인 데이터 유형은 정확성과 성능이 걱정 될 때 중요하기 때문입니다. A char
는 32 비트이고 문자열은 UTF-8로 인코딩됩니다. 그들은 다른 것들입니다.
인덱싱은 멀티 바이트 유니 코드 문자를 반환 할 수 있습니다.
여기에 일치하지 않는 용어가있을 수 있습니다. A char
는 멀티 바이트 유니 코드 문자입니다.
바이트 단위로 이동하면 문자열을 슬라이싱 할 수 있지만 문자 경계에 있지 않으면 표준 라이브러리가 패닉 상태가됩니다.
문자를 얻기 위해 문자열 인덱싱이 구현되지 않은 이유 중 하나는 많은 사람들이 문자열을 ASCII 문자 배열로 오용하기 때문입니다. 문자 를 설정 하기 위해 문자열을 인덱싱하는 것은 결코 효율적일 수 없습니다. 1-4 바이트를 1-4 바이트 값으로 대체 할 수 있어야 나머지 문자열이 상당히 많이 바운스됩니다.
to_uppercase
대문자를 반환 할 수 있습니다.
위에서 언급 ß
했듯이은 대문자로 입력하면 두 문자 가되는 단일 문자입니다 .
솔루션
ASCII 문자 만 대문자로하는 trentcl의 답변 도 참조하십시오 .
실물
코드를 작성해야한다면 다음과 같이 보일 것입니다.
fn some_kind_of_uppercase_first_letter(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().chain(c).collect(),
}
}
fn main() {
println!("{}", some_kind_of_uppercase_first_letter("joe"));
println!("{}", some_kind_of_uppercase_first_letter("jill"));
println!("{}", some_kind_of_uppercase_first_letter("von Hagen"));
println!("{}", some_kind_of_uppercase_first_letter("ß"));
}
그러나 나는 아마도 crates.io 에서 대문자 또는 유니 코드 를 검색하고 나보다 똑똑한 사람이 처리하도록 할 것입니다.
향상
"나보다 똑똑한 사람"에 대해 Veedrac 은 첫 번째 자본 코드 포인트에 액세스 한 후 반복기를 다시 슬라이스로 변환하는 것이 아마도 더 효율적 이라고 지적합니다 . 이것은 memcpy
나머지 바이트를 허용합니다.
fn some_kind_of_uppercase_first_letter(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}
ß
독일어로 해석되는 경우 대문자로 표기하십시오 . 힌트 : 단일 문자가 아닙니다. 문제 진술조차도 복잡 할 수 있습니다. 예를 들어 성의 첫 문자를 대문자로 사용하는 것은 부적절합니다von Hagen
. 이것은 수천 년 동안 서로 다른 관행을 가진 서로 다른 문화를 가진 글로벌 세계에서 사는 것의 한 측면이며 우리는 모든 것을 8 비트와 2 줄의 코드로 뭉치려고 노력하고 있습니다.