Rust 배열
배열(array)은 모두 같은 타입인 값들을 담는, 크기가 고정된 목록이에요. 핵심은 “크기가 고정”이라는 점이에요. 배열은 한 번 만들면 늘리거나 줄일 수 없어요. 크기가 바뀌는 목록이 필요하다면 벡터를 쓰면 돼요.
배열 만들기
섹션 제목: “배열 만들기”fn main() { let numbers: [i32; 5] = [1, 2, 3, 4, 5]; println!("{:?}", numbers);}[i32; 5] 타입은 “i32 값 5개짜리 배열”이라고 읽어요. 길이도 타입의 일부예요. 그래서 [i32; 5]와 [i32; 3]은 서로 다른 타입으로 취급돼요.
타입은 Rust가 추론하게 두고 값만 적어도 돼요.
let numbers = [1, 2, 3, 4, 5];같은 값 반복하기
섹션 제목: “같은 값 반복하기”배열을 같은 값 N개로 채우려면 이렇게 줄여 써요.
fn main() { let zeros = [0; 5]; // [0, 0, 0, 0, 0] println!("{:?}", zeros);}요소에 접근하기
섹션 제목: “요소에 접근하기”배열의 인덱스는 0부터 시작하고, 대괄호를 써요.
fn main() { let fruits = ["사과", "바나나", "체리"];
println!("{}", fruits[0]); // 사과 println!("{}", fruits[2]); // 체리 println!("길이: {}", fruits.len());}범위를 벗어난 접근은 잡아내요
섹션 제목: “범위를 벗어난 접근은 잡아내요”존재하지 않는 인덱스에 접근하려고 하면, Rust는 엉뚱한 메모리를 몰래 읽는 대신 프로그램을 멈춰요.
fn get_fruit(fruits: [&str; 3], index: usize) -> &str { fruits[index]}
fn main() { let fruits = ["사과", "바나나", "체리"]; println!("{}", get_fruit(fruits, 10)); // 실행 중에 패닉이 일어나요}thread 'main' (12345) panicked at src/main.rs:2:5:index out of bounds: the len is 3 but the index is 10이 메시지는 Rust가 영어로 출력해요. “인덱스가 범위를 벗어났어요. 길이는 3인데 인덱스는 10이에요”라는 뜻이고, src/main.rs:2:5는 패닉이 일어난 위치(2번째 줄, 5번째 칸)예요.
배열 순회하기
섹션 제목: “배열 순회하기”fn main() { let numbers = [10, 20, 30];
for n in numbers { println!("{n}"); }}배열의 배열 (2차원 배열)
섹션 제목: “배열의 배열 (2차원 배열)”배열은 다른 배열을 담을 수 있어요. 그러면 게임판이나 작은 스프레드시트처럼 행과 열이 있는 격자가 돼요. 아래 grid의 타입은 [[i32; 3]; 2]이고, “각각 i32 값 3개짜리 배열인 행이 2개”라고 읽어요.
fn main() { // 2행 3열 let grid = [ [1, 2, 3], [4, 5, 6], ];
println!("1행 2열: {}", grid[1][2]);
let mut total = 0; for row in grid { println!("{:?}", row); for value in row { total += value; } } println!("합계: {total}");}실행 결과:
1행 2열: 6[1, 2, 3][4, 5, 6]합계: 21grid[1][2]는 “1행, 그리고 그 행 안의 2열”이라는 뜻이에요. 둘 다 0부터 세기 때문에 두 번째 행의 세 번째 값이에요. 모든 값을 방문하려면 행을 도는 반복문 하나와, 그 안에서 각 행의 값을 도는 반복문 하나를 써요.
모든 행의 길이는 같아야 해요. 행의 길이가 타입의 일부이기 때문이에요. 순회하면서 각 위치도 필요하다면 .iter().enumerate()로 인덱스와 값을 함께 얻을 수 있어요. for 반복문 페이지에 나와 있어요.
배열과 벡터
섹션 제목: “배열과 벡터”크기가 고정되어 있고 미리 알 수 있을 때(예를 들어 일주일의 7일) 배열을 쓰세요. 항목을 추가하거나 빼야 할 때는 Vec을 쓰세요. 실제로는 대부분이 이 경우예요. 일상적인 Rust 코드에서 배열은 벡터보다 덜 쓰여요.
연습 문제
섹션 제목: “연습 문제”1. 합계와 평균
섹션 제목: “1. 합계와 평균”배열 [4, 8, 15, 16, 23, 42]를 만드세요. 모든 값을 더한 다음, 합계와 소수점 두 자리까지의 평균을 출력해 보세요. 힌트: for로 돌면서 total에 계속 더하고, 나누기 전에 두 숫자를 as로 f64로 바꾸세요.
정답 보기
fn main() { let numbers = [4, 8, 15, 16, 23, 42];
let mut total = 0; for n in numbers { total += n; }
let average = total as f64 / numbers.len() as f64; println!("합계: {total}"); println!("평균: {average:.2}");}실행 결과:
합계: 108평균: 18.00as f64가 없으면 total / numbers.len()은 정수 나눗셈이 돼요. 게다가 total(i32)과 len()(usize)의 타입이 달라서 Rust가 에러를 내요.
2. 가장 더운 날
섹션 제목: “2. 가장 더운 날”일주일 동안의 기온 [18, 25, 12, 31, 22, 27, 19]가 있어요. 가장 높은 기온을 찾아서 출력해 보세요. 힌트: let mut hottest = temps[0];으로 시작한 다음, 반복하면서 더 큰 값을 찾을 때마다 바꿔 넣으세요.
정답 보기
fn main() { let temps = [18, 25, 12, 31, 22, 27, 19];
let mut hottest = temps[0]; for t in temps { if t > hottest { hottest = t; } }
println!("가장 더운 날의 기온: {hottest}");}실행 결과:
가장 더운 날의 기온: 310이 아니라 temps[0]에서 시작하는 게 중요해요. 모든 기온이 영하라면 0에서 시작했을 때 틀린 답이 나오거든요.
- 배열은 고정된 길이를 가지고, 그 길이는 타입의 일부예요:
[i32; 5]. - 요소에는
array[index]로 접근하고, 인덱스는 0부터 시작해요. - 범위를 벗어난 접근은 정의되지 않은 동작 대신 실행 중 패닉을 일으켜요.
- 배열은 배열을 담을 수 있어요:
[[i32; 3]; 2]는grid[행][열]로 읽는 격자예요. - 크기를 바꿔야 한다면
Vec을 쓰세요.
이해도 점검
섹션 제목: “이해도 점검”이해도 점검
1. Rust 배열의 길이에 대해 맞는 설명은 무엇일까요?
2. 실행 중에 범위를 벗어난 배열 인덱스에 접근하면 어떻게 될까요?
3. let zeros = [0; 5];는 무엇을 만들까요?
점수: 0 / 3
더 알아보기
섹션 제목: “더 알아보기”- 배열 타입 — The Rust Programming Language 한국어판: 길이가 왜 타입의 일부인지를 포함해 배열을 소개하는 공식 입문서예요.
- Arrays and Slices — Rust by Example (영어): 짧은 예제를 실행해 볼 수 있고, 슬라이스도 처음으로 살짝 맛볼 수 있어요.
- for를 이용한 컬렉션에 대한 반복문 — The Rust Programming Language 한국어판: 인덱스로 배열을 도는 것보다
for반복문이 왜 더 안전한지 설명해요. array— 표준 라이브러리 문서 (영어):map,as_slice처럼 배열이 할 수 있는 일과, 배열이 슬라이스 메서드를 모두 빌려 쓰는 방식을 설명해요.