티스토리 뷰

Rust-Language

Slices

kmj24 2021. 4. 5. 01:22

소유권을 갖지 않는 또다른 데이터 타입은 슬라이스이다.

슬라이스는 collection 전체가 아닌 collection의 연속된 일련의 요소들을 참조할 수 있게 함.

 

//소유권을 갖지 않는 데이터타입.
fn first_word(s : &String) -> usize {
    //바이트 배열로 변환
    let bytes = s.as_bytes();
    //iter() : 반복자 //enumerate() : 튜플형식으로 반환
    //bytes의 인덱스 i, 참조값 &item
    for(i, &item) in bytes.iter().enumerate(){
        if item == b' '{
            return i;
        }
    }
    s.len()
}

pub fn run(){
    let mut s = String::from("te st");
    let len = first_word(&s);
    s.clear();
    println!("{}", len);
}

여기서 run()함수를 실행시켰을때, s에 문자열 "te st"가 할당되고, 변수 len에는 first_word가 실행된 결과인 2가 할당될 것이다. 

 그 다음 first_word에 argument로 넘긴 s의 값을 clear로 내용을 비우고 ""상태가 되게 한다.

len은 여전히 값을 가지고 있지만, 변수 s와 싱크가 맞지 않게 된다.

이를 해결할 수 있는 것은 string slice이다.

 

String Slice

String의 일부분에 대한 참조자이다.

형태는 다음과 같다.

pub fn run(){
    let ss = String::from("String Slice");
    let _string = &ss[0..6];
    let _slice = &ss[7..11];
}

String의 참조자를 가지게 되는건 비슷하지만, 일부분에 대한 참조자를 가지고 있는 것이다.

선언된 형태를 보면 알겠지만 참조할 문자열의 "[시작인덱스..끝인덱스+1]" 형태이다.

시작과 끝부분은 요렇게도 작성 가능하다.

let ss = String::from("test");
let start_slice = &ss[..2];
let end_slice = &ss[2..];
let total = &ss[..];

 

이제 가장 위에서 작성했던 코드를 다시 작성해보자.

(String Slice는 &str타입으로 반환)

fn first_word(s : &String) -> &str {
    let bytes = s.as_bytes();

    for(i, &item) in bytes.iter().enumerate(){
        if item == b' '{
            return &s[0..i];
        }
    }
    &s[..]
}

pub fn run(){
    let mut s = String::from("test");
    let len = first_word(&s);
    s.clear();
    println!("{}", len);
}

위 코드를 실행하면 다음과 같은 오류가 발생한다.

불변 참조자를 만들었을 경우 가변 참조자를 만들 수 없다.

clear함수가 String을 비울 때, 가변 참조자를 갖기위한 시도를 하고 실패를 하게 된다. (&str은 불변참조자)

 

String literal은 slice이다.

여기서 s의 data type은 &str이다.

let s = "test";

이것은 바이너리의 특정 지점을 가지고 있는 Slice고 String literal이 불변인지에 대한 이유가 된다. &str은 불변참조자이다.

 

Parameter로써의 String Slice

위의 first_word함수를 한번 더 개선한 모습이다.

fn first_word(s : &str) -> &str {
    let bytes = s.as_bytes();

    for(i, &item) in bytes.iter().enumerate(){
        if item == b' '{
            return &s[0..i];
        }
    }
    &s[..]
}

pub fn run(){
    //let mut s = String::from("test");
    let s = "test";
    let len = first_word(&s);
    println!("{}", len);
}

만약 String Sliece를 argument로 바로 넘길 수 있고, 또한 String을 넘긴다면 String전체의 slice를 넘길 수 있다.

 

이 장의 전체 코드

//소유권을 갖지 않는 데이터타입.
fn first_word(s : &str) -> &str {
    //바이트 배열로 변환
    let bytes = s.as_bytes();

    for(i, &item) in bytes.iter().enumerate(){
        if item == b' '{
            return &s[0..i];
        }
    }
    &s[..]
}

pub fn run(){
    //let s = String::from("test");
    let s = "test";
    let len = first_word(&s);
    //s.clear();
    println!("{}", len);
}

 

 

참고 : rinthel.github.io/rust-lang-book-ko/ch04-03-slices.html

 

슬라이스 - The Rust Programming Language

소유권을 갖지 않는 또다른 데이터 타입은 슬라이스입니다. 슬라이스는 여러분이 컬렉션(collection) 전체가 아닌 컬렉션의 연속된 일련의 요소들을 참조할 수 있게 합니다. 여기 작은 프로그래밍

rinthel.github.io

 

'Rust-Language' 카테고리의 다른 글

method  (0) 2021.04.07
구조체  (0) 2021.04.07
참조자와 빌림  (0) 2021.04.03
소유권(Ownership)  (0) 2021.04.02
제어문  (0) 2021.03.30
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함