Rust-퀵 가이드

Rust는 Graydon Hoare가 개발 한 시스템 수준의 프로그래밍 언어입니다. Mozilla Labs는 나중에 프로그램을 인수했습니다.

애플리케이션 v / s 시스템 프로그래밍 언어

Java / C #과 같은 애플리케이션 프로그래밍 언어는 사용자에게 직접 서비스를 제공하는 소프트웨어를 구축하는 데 사용됩니다. 스프레드 시트, 워드 프로세서, 웹 애플리케이션 또는 모바일 애플리케이션과 같은 비즈니스 애플리케이션을 구축하는 데 도움이됩니다.

C / C ++와 같은 시스템 프로그래밍 언어는 소프트웨어 및 소프트웨어 플랫폼을 구축하는 데 사용됩니다. 운영 체제, 게임 엔진, 컴파일러 등을 구축하는 데 사용할 수 있습니다. 이러한 프로그래밍 언어에는 상당한 수준의 하드웨어 상호 작용이 필요합니다.

시스템과 응용 프로그래밍 언어는 두 가지 주요 문제에 직면합니다.

  • 보안 코드를 작성하는 것은 어렵습니다.
  • 다중 스레드 코드를 작성하는 것은 어렵습니다.

왜 Rust인가?

Rust는 세 가지 목표에 중점을 둡니다.

  • Safety
  • Speed
  • Concurrency

이 언어는 매우 안정적이고 빠른 소프트웨어를 간단한 방법으로 개발하도록 설계되었습니다. Rust를 사용하여 고급 프로그램을 하드웨어 특정 프로그램으로 작성할 수 있습니다.

공연

Rust 프로그래밍 언어에는 설계 상 가비지 수집기 (GC)가 없습니다. 이것은 런타임에 성능을 향상시킵니다.

컴파일 타임에 메모리 안전성

Rust를 사용하여 빌드 된 소프트웨어는 댕글 링 포인터, 버퍼 오버런 및 메모리 누수와 같은 메모리 문제로부터 안전합니다.

다중 스레드 응용 프로그램

Rust의 소유권 및 메모리 안전 규칙은 데이터 경합없이 동시성을 제공합니다.

웹 어셈블리 (WASM) 지원

웹 어셈블리는 브라우저, 임베디드 장치 또는 다른 곳에서 계산 집약적 인 알고리즘을 실행하는 데 도움이됩니다. 네이티브 코드의 속도로 실행됩니다. Rust는 빠르고 안정적인 실행을 위해 웹 어셈블리로 컴파일 할 수 있습니다.

Rust의 설치는 rustup, Rust 버전 및 관련 도구를 관리하기위한 콘솔 기반 도구입니다.

Windows에 설치

Windows에 RUST를 설치하는 방법을 알아 보겠습니다.

  • Windows에서 Rust 프로그램을 실행하려면 Visual Studio 2013 이상을 C ++ 도구와 함께 설치해야합니다. 먼저 여기에서 Visual Studio를 다운로드하십시오 .VS 2013 Express

  • 다운로드 및 설치 rustup Windows 용 도구. rustup-init.exe여기에서 다운로드 가능합니다 − Rust Lang

  • 더블 클릭 rustup-init.exe파일. 클릭하면 다음 화면이 나타납니다.

  • 기본 설치를 위해 Enter 를 누르십시오 . 설치가 완료되면 다음 화면이 나타납니다.

  • 설치 화면에서 Rust 관련 파일이 폴더에 저장되어 있음이 분명합니다.

    C : \ Users \ {PC} \. cargo \ bin

폴더의 내용은-

cargo-fmt.exe
cargo.exe
rls.exe
rust-gdb.exe
rust-lldb.exe
rustc.exe // this is the compiler for rust
rustdoc.exe
rustfmt.exe
rustup.exe
  • CargoRust의 패키지 관리자입니다. 확인하려면cargo 설치되면 다음 명령을 실행하십시오-

C:\Users\Admin>cargo -V
cargo 1.29.0 (524a578d7 2018-08-05)
  • Rust 용 컴파일러는 rustc. 컴파일러 버전을 확인하려면 다음 명령을 실행하십시오.

C:\Users\Admin>cargo -V
cargo 1.29.0 (524a578d7 2018-08-05)

Linux / Mac에 설치

설치하기 위해서 rustup Linux 또는 macOS에서는 터미널을 열고 다음 명령을 입력합니다.

$ curl https://sh.rustup.rs -sSf | sh

이 명령은 스크립트를 다운로드하고 설치를 시작합니다. rustup최신 안정 버전의 Rust를 설치하는 도구입니다. 암호를 입력하라는 메시지가 표시 될 수 있습니다. 설치에 성공하면 다음 줄이 나타납니다.

Rust is installed now. Great!

설치 스크립트는 다음 로그인 후 시스템 PATH에 Rust를 자동으로 추가합니다. 터미널을 다시 시작하는 대신 Rust를 바로 사용하려면 쉘에서 다음 명령을 실행하여 시스템 PATH에 수동으로 Rust를 추가하십시오.

$ source $HOME/.cargo/env

또는 ~ / .bash_profile에 다음 줄을 추가 할 수 있습니다.

$ export PATH="$HOME/.cargo/bin:$PATH"

NOTE − Rust 프로그램을 컴파일하려고 할 때 링커를 실행할 수 없다는 오류가 발생하면 링커가 시스템에 설치되어 있지 않으며 수동으로 설치해야합니다.

RUST를위한 튜토리얼 포인트 코딩 그라운드 사용

REPL (Read-Evaluate-Print Loop)은 컴퓨터 프로그램을 컴파일하고 실행하기 위해 사용하기 쉬운 대화 형 쉘입니다. 브라우저에서 온라인으로 Rust 프로그램을 컴파일하고 실행하려면 Tutorialspoint Coding Ground를 사용하세요 .

이 장에서는 다음을 통해 Rust 언어의 기본 구문을 설명합니다. HelloWorld 예.

  • 만들기 HelloWorld-App 폴더를 열고 터미널의 해당 폴더로 이동하십시오.

C:\Users\Admin>mkdir HelloWorld-App
C:\Users\Admin>cd HelloWorld-App
C:\Users\Admin\HelloWorld-App>
  • Rust 파일을 생성하려면 다음 명령을 실행하십시오-

C:\Users\Admin\HelloWorld-App>notepad Hello.rs

Rust 프로그램 파일의 확장자는 .rs입니다. 위의 명령은 빈 파일을 만듭니다.Hello.rs메모장에서 엽니 다. 이 파일에 아래 주어진 코드를 추가하십시오-

fn
main(){
   println!("Rust says Hello to TutorialsPoint !!");
}

위의 프로그램은 main fn main () 함수를 정의합니다 . FN 키워드는 함수를 정의하는 데 사용됩니다. ) (주요 프로그램에 대한 진입 점의 역할을 소정의 함수이다. println! Rust에서 미리 정의 된 매크로입니다. 콘솔에 문자열 (여기서는 Hello)을 인쇄하는 데 사용됩니다. 매크로 호출에는 항상 느낌표가 표시됩니다 – ! .

  • 컴파일 Hello.rs 파일 사용 rustc.

C:\Users\Admin\HelloWorld-App>rustc Hello.rs

프로그램을 성공적으로 컴파일하면 실행 파일 ( file_name.exe )이 생성됩니다. .exe 파일이 생성 되었는지 확인하려면 다음 명령을 실행하십시오.

C:\Users\Admin\HelloWorld-App>dir
//lists the files in folder
Hello.exe
Hello.pdb
Hello.rs
  • Hello.exe 파일을 실행하고 출력을 확인하십시오.

매크로 란?

Rust는 메타 프로그래밍이 가능한 강력한 매크로 시스템을 제공합니다. 앞의 예에서 보았 듯이 매크로는 이름이 bang (!)으로 끝나는 것을 제외하고는 함수처럼 보이지만 함수 호출을 생성하는 대신 매크로는 나머지 프로그램과 함께 컴파일되는 소스 코드로 확장됩니다. 따라서 함수와 달리 프로그램에 더 많은 런타임 기능을 제공합니다. 매크로는 기능의 확장 버전입니다.

println! 사용 매크로-구문

println!(); // prints just a newline
println!("hello ");//prints hello
println!("format {} arguments", "some"); //prints format some arguments

Rust의 주석

주석은 프로그램의 가독성을 향상시키는 방법입니다. 주석은 코드 작성자, 함수 / 구조에 대한 힌트 등과 같은 프로그램에 대한 추가 정보를 포함하는 데 사용할 수 있습니다. 컴파일러는 주석을 무시합니다.

Rust는 다음 유형의 주석을 지원합니다.

  • 한 줄 주석 (//) − //과 줄 끝 사이의 모든 텍스트는 주석으로 처리됩니다.

  • 여러 줄 주석 (/ * * /)-이 주석은 여러 줄에 걸쳐있을 수 있습니다.

//this is single line comment

/* This is a
   Multi-line comment
*/

온라인으로 실행

Rust 프로그램은 Tutorialspoint Coding Ground를 통해 온라인으로 실행할 수 있습니다 . Editor 탭에서 HelloWorld 프로그램을 작성하고 Execute를 클릭하여 결과를 확인합니다.

유형 시스템은 언어에서 지원하는 다양한 유형의 값을 나타냅니다. 유형 시스템은 프로그램에 의해 저장되거나 조작되기 전에 제공된 값의 유효성을 확인합니다. 이렇게하면 코드가 예상대로 작동합니다. 타입 시스템은 더욱 풍부한 코드 힌트와 자동화 된 문서화를 허용합니다.

Rust는 정적으로 형식화 된 언어입니다. Rust의 모든 값은 특정 데이터 유형입니다. 컴파일러는 할당 된 값을 기반으로 변수의 데이터 유형을 자동으로 추론 할 수 있습니다.

변수 선언

사용 let 변수를 선언하는 키워드입니다.

fn main() {
   let company_string = "TutorialsPoint";  // string type
   let rating_float = 4.5;                 // float type
   let is_growing_boolean = true;          // boolean type
   let icon_char = '♥';                    //unicode character type

   println!("company name is:{}",company_string);
   println!("company rating on 5 is:{}",rating_float);
   println!("company is growing :{}",is_growing_boolean);
   println!("company icon is:{}",icon_char);
}

위의 예에서 변수의 데이터 유형은 할당 된 값에서 추론됩니다. 예를 들어 Rust는 string 데이터 유형을 company_string 변수에 할당 하고 float 데이터 유형을 rating_float 등에 할당합니다 .

에 println! 매크로는 두 개의 인수를 취합니다-

  • 자리 표시자인 특수 구문 {}
  • 변수 이름 또는 상수

자리 표시자는 변수 값으로 대체됩니다.

위 코드 스 니펫의 출력은 다음과 같습니다.

company name is: TutorialsPoint
company rating on 5 is:4.5
company is growing: true
company icon is: ♥

스칼라 유형

스칼라 유형은 단일 값을 나타냅니다. 예 : 10,3.14, 'c'. Rust에는 네 가지 기본 스칼라 유형이 있습니다.

  • Integer
  • Floating-point
  • Booleans
  • Characters

이후 섹션에서 각 유형에 대해 배웁니다.

정수

정수는 분수 구성 요소가없는 숫자입니다. 간단히 말해 정수 데이터 유형은 정수를 나타내는 데 사용됩니다.

정수는 부호 있음 및 부호 없음으로 추가로 분류 할 수 있습니다. 부호있는 정수는 음수와 양수 값을 모두 저장할 수 있습니다. 부호없는 정수는 양수 값만 저장할 수 있습니다. 정수 유형이 아래에 주어지면 자세한 설명-

Sr. 아니. 크기 서명 됨 서명되지 않음
1 8 비트 i8 u8
2 16 비트 i16 u16
32 비트 i32 u32
4 64 비트 i64 u64
5 128 비트 i128 u128
6 아치 Isize 사용하다

정수의 크기는 arch 가 될 수 있습니다 . 이는 데이터 유형의 크기가 머신 의 아키텍처 에서 파생된다는 것을 의미합니다 . 크기가 arch 인 정수 는 x86 시스템에서 32 비트, x64 시스템에서 64 비트입니다. 아치 정수는 주로 일종의 컬렉션을 인덱싱 할 때 사용됩니다.

삽화

fn main() {
   let result = 10;    // i32 by default
   let age:u32 = 20;
   let sum:i32 = 5-15;
   let mark:isize = 10;
   let count:usize = 30;
   println!("result value is {}",result);
   println!("sum is {} and age is {}",sum,age);
   println!("mark is {} and count is {}",mark,count);
}

출력은 다음과 같습니다.

result value is 10
sum is -10 and age is 20
mark is 10 and count is 30

age 값을 부동 소수점 값으로 바꾸면 위 코드는 컴파일 오류를 반환 합니다.

정수 범위

각 부호있는 변형은 -(2 ^ (n-1)에서 2 ^ (n-1) -1 까지의 숫자를 저장할 수 있습니다. 여기서 n은 변형이 사용하는 비트 수입니다. 예를 들어 i8은 -(2 ^의 숫자를 저장할 수 있습니다. 7) ~ 2 ^ 7 -1 − 여기서 n 을 8 로 대체했습니다 .

부호없는 각 변형은 0 에서 (2 ^ n) -1 까지의 숫자를 저장할 수 있습니다 . 예를 들어 u8은 0 에서 2 ^ 7 까지의 숫자를 저장할 수 있으며 이는 0에서 255와 같습니다.

정수 오버플로

정수 변수에 할당 된 값이 데이터 유형에 대해 Rust가 정의한 범위를 초과하면 정수 오버플로가 발생합니다. 예를 들어 이것을 이해합시다.

fn main() {
   let age:u8 = 255;

   // 0 to 255 only allowed for u8
   let weight:u8 = 256;   //overflow value is 0
   let height:u8 = 257;   //overflow value is 1
   let score:u8 = 258;    //overflow value is 2

   println!("age is {} ",age);
   println!("weight is {}",weight);
   println!("height is {}",height);
   println!("score is {}",score);
}

부호없는 u8 변수의 유효한 범위는 0에서 255까지입니다. 위의 예에서 변수에는 255보다 큰 값이 할당됩니다 (Rust의 정수 변수에 대한 상한값). 실행시 위의 코드는 경고를 반환합니다.warning − literal out of range for u8체중, 키, 점수 변수 255 이후의 오버플로 값은 0, 1, 2 등에서 시작됩니다. 경고없는 최종 출력은 다음과 같습니다.

age is 255
weight is 0
height is 1
score is 2

흙손

Rust의 Float 데이터 유형은 다음과 같이 분류 할 수 있습니다. f32f64. f32 유형은 단 정밀도 부동이고 f64에는 배정 밀도가 있습니다. 기본 유형은 f64입니다. float 데이터 유형에 대해 더 많이 이해하려면 다음 예제를 고려하십시오.

fn main() {
   let result = 10.00;        //f64 by default
   let interest:f32 = 8.35;
   let cost:f64 = 15000.600;  //double precision
   
   println!("result value is {}",result);
   println!("interest is {}",interest);
   println!("cost is {}",cost);
}

출력은 다음과 같습니다.

interest is 8.35
cost is 15000.6

자동 형 주조

Rust에서는 자동 유형 캐스팅이 허용되지 않습니다. 다음 코드 스 니펫을 고려하십시오. float 변수에 정수 값이 할당됩니다.interest.

fn main() {
   let interest:f32 = 8;   // integer assigned to float variable
   println!("interest is {}",interest);
}

컴파일러는 mismatched types error 아래와 같이.

error[E0308]: mismatched types
   --> main.rs:2:22
   |
 2 | let interest:f32=8;
   |    ^ expected f32, found integral variable
   |
   = note: expected type `f32`
      found type `{integer}`
error: aborting due to previous error(s)

숫자 구분자

큰 숫자의 가독성을 높이기 위해 시각적 구분 기호 _ 밑줄을 사용하여 숫자를 구분할 수 있습니다. 즉, 50,000은 50_000으로 쓸 수 있습니다. 이것은 아래 예에 나와 있습니다.

fn main() {
   let float_with_separator = 11_000.555_001;
   println!("float value {}",float_with_separator);
   
   let int_with_separator = 50_000;
   println!("int value {}",int_with_separator);
}

출력은 다음과 같습니다.

float value 11000.555001
int value 50000

부울

부울 유형에는 true 또는 false의 두 가지 가능한 값이 있습니다. 사용bool 부울 변수를 선언하는 키워드입니다.

삽화

fn main() {
   let isfun:bool = true;
   println!("Is Rust Programming Fun ? {}",isfun);
}

위 코드의 출력은 다음과 같습니다.

Is Rust Programming Fun ? true

캐릭터

Rust의 문자 데이터 유형은 숫자, 알파벳, 유니 코드 및 특수 문자를 지원합니다. 사용char문자 데이터 유형의 변수를 선언하는 키워드입니다. Rust의 char 유형은 유니 코드 스칼라 값을 나타내며, 이는 단순한 ASCII 이상을 나타낼 수 있음을 의미합니다. 유니 코드 스칼라 값 범위U+0000 ...에 U+D7FFU+E000 ...에 U+10FFFF 포함한.

Character 데이터 유형에 대해 더 많이 이해하기위한 예를 고려해 보겠습니다.

fn main() {
   let special_character = '@'; //default
   let alphabet:char = 'A';
   let emoji:char = '';
   
   println!("special character is {}",special_character);
   println!("alphabet is {}",alphabet);
   println!("emoji is {}",emoji);
}

위 코드의 출력은 다음과 같습니다.

special character is @
alphabet is A
emoji is

변수는 프로그램이 조작 할 수있는 명명 된 저장소입니다. 간단히 말해 변수는 프로그램이 값을 저장하는 데 도움이됩니다. Rust의 변수는 특정 데이터 유형과 관련이 있습니다. 데이터 유형은 변수 메모리의 크기와 레이아웃, 해당 메모리 내에 저장할 수있는 값의 범위 및 변수에 대해 수행 할 수있는 작업 집합을 결정합니다.

변수 이름 지정 규칙

이 섹션에서는 변수 이름 지정에 대한 다양한 규칙에 대해 알아 봅니다.

  • 변수 이름은 문자, 숫자 및 밑줄 문자로 구성 될 수 있습니다.

  • 문자 또는 밑줄로 시작해야합니다.

  • Rust는 대소 문자를 구분하기 때문에 대문자와 소문자는 구별됩니다.

통사론

Rust에서 변수를 선언하는 동안 데이터 유형은 선택 사항입니다. 데이터 유형은 변수에 지정된 값에서 유추됩니다.

변수 선언 구문은 다음과 같습니다.

let variable_name = value;            // no type specified
let variable_name:dataType = value;   //type specified

삽화

fn main() {
   let fees = 25_000;
   let salary:f64 = 35_000.00;
   println!("fees is {} and salary is {}",fees,salary);
}

위 코드의 출력은 다음과 같습니다. fees is 25000 and salary is 35000.

불변

기본적으로 변수는 불변입니다. Rust에서만 읽기만 가능합니다. 즉, 값이 변수 이름에 바인딩 된 후에는 변수 값을 변경할 수 없습니다.

예를 들어 이것을 이해합시다.

fn main() {
   let fees = 25_000;
   println!("fees is {} ",fees);
   fees = 35_000;
   println!("fees changed is {}",fees);
}

출력은 다음과 같습니다.

error[E0384]: re-assignment of immutable variable `fees`
 --> main.rs:6:3
   |
 3 | let fees = 25_000;
   | ---- first assignment to `fees`
...
 6 | fees=35_000;
   | ^^^^^^^^^^^ re-assignment of immutable variable

error: aborting due to previous error(s)

오류 메시지는 오류의 원인을 나타냅니다. 변경 불가능한 변수 수수료에 값을 두 번 할당 할 수 없습니다. 이것은 Rust가 프로그래머가 코드를 작성할 수 있도록 허용하고 안전성과 쉬운 동시성을 활용하는 여러 가지 방법 중 하나입니다.

변하기 쉬운

변수는 기본적으로 변경할 수 없습니다. 변수 이름 앞에mut변경 가능하도록 키워드. 가변 변수의 값은 변경 될 수 있습니다.

가변 변수를 선언하는 구문은 다음과 같습니다.

let mut variable_name = value;
let mut variable_name:dataType = value;
Let us understand this with an example

fn main() {
   let mut fees:i32 = 25_000;
   println!("fees is {} ",fees);
   fees = 35_000;
   println!("fees changed is {}",fees);
}

스 니펫의 출력은 다음과 같습니다.

fees is 25000
fees changed is 35000

상수는 변경할 수없는 값을 나타냅니다. 상수를 선언하면 그 값이 변할 수 없습니다. 상수를 사용하는 키워드는 다음과 같습니다.const. 상수는 명시 적으로 입력해야합니다. 다음은 상수를 선언하는 구문입니다.

const VARIABLE_NAME:dataType = value;

Rust 상수 명명 규칙

상수의 명명 규칙은 변수의 명명 규칙과 유사합니다. 상수 이름의 모든 문자는 일반적으로 대문자입니다. 변수 선언과 달리let 키워드는 상수를 선언하는 데 사용되지 않습니다.

아래 예제에서 Rust에서 상수를 사용했습니다.

fn main() {
   const USER_LIMIT:i32 = 100;    // Declare a integer constant
   const PI:f32 = 3.14;           //Declare a float constant

   println!("user limit is {}",USER_LIMIT);  //Display value of the constant
   println!("pi value is {}",PI);            //Display value of the constant
}

상수 대 변수

이 섹션에서는 상수와 변수의 차별화 요소에 대해 알아 봅니다.

  • 상수는 const 키워드를 사용하여 변수를 선언하는 동안 let 예어.

  • 변수 선언은 선택적으로 데이터 유형을 가질 수 있지만 상수 선언은 데이터 유형을 지정해야합니다. 즉, const USER_LIMIT = 100은 오류를 발생시킵니다.

  • 다음을 사용하여 선언 된 변수 let키워드는 기본적으로 변경할 수 없습니다. 그러나 다음을 사용하여 변경하는 옵션이 있습니다.mut예어. 상수는 변경할 수 없습니다.

  • 상수는 함수 호출의 결과 나 런타임에 계산 될 다른 값이 아닌 상수 식으로 만 설정할 수 있습니다.

  • 상수는 전역 범위를 포함하여 모든 범위에서 선언 할 수 있으므로 코드의 많은 부분에서 알아야하는 값에 유용합니다.

변수와 상수의 섀도 잉

Rust는 프로그래머가 같은 이름의 변수를 선언 할 수 있도록합니다. 이 경우 새 변수가 이전 변수를 재정의합니다.

예를 들어 이것을 이해합시다.

fn main() {
   let salary = 100.00;
   let salary = 1.50 ; 
   // reads first salary
   println!("The value of salary is :{}",salary);
}

위의 코드는 salary라는 이름으로 두 개의 변수를 선언합니다. 첫 번째 선언에는 100.00이 지정되고 두 번째 선언에는 1.50이 지정됩니다. 두 번째 변수는 출력을 표시하는 동안 첫 번째 변수를 숨기거나 숨 깁니다.

산출

The value of salary is :1.50

Rust는 섀도 잉하는 동안 데이터 유형이 다른 변수를 지원합니다.

다음 예를 고려하십시오.

코드는 이름으로 두 개의 변수를 선언합니다. uname. 첫 번째 선언에는 문자열 값이 할당되고 두 번째 선언에는 정수가 할당됩니다. len 함수는 문자열 값의 총 문자 수를 반환합니다.

fn main() {
   let uname = "Mohtashim";
   let uname = uname.len();
   println!("name changed to integer : {}",uname);
}

산출

name changed to integer: 9

변수와 달리 상수는 음영 처리 될 수 없습니다. 위 프로그램의 변수가 상수로 대체되면 컴파일러에서 오류가 발생합니다.

fn main() {
   const NAME:&str = "Mohtashim";
   const NAME:usize = NAME.len(); 
   //Error : `NAME` already defined
   println!("name changed to integer : {}",NAME);
}

Rust의 문자열 데이터 유형은 다음과 같이 분류 할 수 있습니다.

  • 문자열 리터럴(&str)

  • 문자열 개체(String)

문자열 리터럴

문자열 리터럴 (& str)은 컴파일 타임에 문자열의 값을 알 때 사용됩니다. 문자열 리터럴은 변수로 하드 코딩되는 문자 집합입니다. 예를 들어 let company = "Tutorials Point" . 문자열 리터럴은 std :: str 모듈에 있습니다. 문자열 리터럴은 문자열 조각이라고도합니다.

다음 예제는 회사위치 라는 두 개의 문자열 리터럴을 선언합니다 .

fn main() {
   let company:&str="TutorialsPoint";
   let location:&str = "Hyderabad";
   println!("company is : {} location :{}",company,location);
}

문자열 리터럴은 기본적으로 정적입니다. 이는 문자열 리터럴이 전체 프로그램 기간 동안 유효하다는 것을 의미합니다. 다음과 같이 명시 적으로 변수를 정적으로 지정할 수도 있습니다.

fn main() {
   let company:&'static str = "TutorialsPoint";
   let location:&'static str = "Hyderabad";
   println!("company is : {} location :{}",company,location);
}

위의 프로그램은 다음 출력을 생성합니다-

company is : TutorialsPoint location :Hyderabad

문자열 개체

String 개체 유형은 표준 라이브러리에서 제공됩니다. 문자열 리터럴과 달리 문자열 개체 유형은 핵심 언어의 일부가 아닙니다. 표준 라이브러리 pub struct String 에서 공용 구조로 정의됩니다 . String은 성장 가능한 컬렉션입니다. 변경 가능하고 UTF-8 인코딩 유형입니다. 그만큼String개체 유형을 사용하여 런타임에 제공되는 문자열 값을 나타낼 수 있습니다. 문자열 개체가 힙에 할당됩니다.

통사론

String 객체를 생성하려면 다음 구문 중 하나를 사용할 수 있습니다.

String::new()

위의 구문은 빈 문자열을 만듭니다.

String::from()

그러면 매개 변수로 전달 된 일부 기본값이있는 문자열이 생성됩니다. from() 방법.

다음 예제는 String 객체의 사용을 보여줍니다.

fn main(){
   let empty_string = String::new();
   println!("length is {}",empty_string.len());

   let content_string = String::from("TutorialsPoint");
   println!("length is {}",content_string.len());
}

위의 예제는 새로운 메소드를 사용하는 빈 문자열 객체 와 from 메소드를 사용하는 문자열 리터럴에서 문자열 객체라는 두 개의 문자열을 생성 합니다 .

출력은 다음과 같습니다.

length is 0
length is 14

일반적인 방법-문자열 객체

Sr. 아니. 방법 서명 기술
1 새로운() pub const fn new () → 문자열 비어있는 새 문자열을 만듭니다.
2 to_string () fn to_string (& self) → 문자열 주어진 값을 String으로 변환합니다.
바꾸다() pub fn replace < 'a, P> (&'a self, from : P, to : & str) → 문자열 패턴의 모든 일치를 다른 문자열로 바꿉니다.
4 as_str () pub fn as_str (& self) → & str 전체 문자열을 포함하는 문자열 조각을 추출합니다.
5 푸시() pub fn push (& mut self, ch : char) 이 문자열의 끝에 지정된 문자를 추가합니다.
6 push_str () pub fn push_str (& mut self, 문자열 : & str) 이 String의 끝에 지정된 문자열 조각을 추가합니다.
7 len () pub fn len (& self) → 사용 이 문자열의 길이를 바이트 단위로 반환합니다.
8 손질() pub fn trim (& self) → & str 선행 및 후행 공백이 제거 된 문자열 조각을 반환합니다.
9 split_whitespace () pub fn split_whitespace (& self) → SplitWhitespace 공백으로 문자열 조각을 분할하고 반복자를 반환합니다.
10 스플릿() pub fn split < 'a, P> (&'a self, pat : P) → Split < 'a, P>, 여기서 P는 패턴이 & str, char 또는 분할을 결정하는 클로저 일 수 있습니다. 패턴과 일치하는 문자로 구분 된이 문자열 조각의 하위 문자열에 대한 반복기를 반환합니다.
11 chars () pub fn chars (& self) → Chars 문자열 조각의 문자에 대한 반복자를 반환합니다.

그림 : new ()

빈 문자열 객체는 new()메소드와 그 값은 hello 로 설정됩니다 .

fn main(){
   let mut z = String::new();
   z.push_str("hello");
   println!("{}",z);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

hello

그림 : to_string ()

String 객체의 모든 메서드에 액세스하려면 다음을 사용하여 문자열 리터럴을 객체 유형으로 변환합니다. to_string() 함수.

fn main(){
   let name1 = "Hello TutorialsPoint , 
   Hello!".to_string();
   println!("{}",name1);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

Hello TutorialsPoint , Hello!

그림 : replace ()

그만큼 replace()함수는 두 개의 매개 변수를 취합니다. 첫 번째 매개 변수는 검색 할 문자열 패턴이고 두 번째 매개 변수는 대체 할 새 값입니다. 위의 예에서 Helloname1 문자열 에 두 번 나타납니다 .

replace 함수는 문자열의 모든 항목을 대체합니다. HelloHowdy.

fn main(){
   let name1 = "Hello TutorialsPoint , 
   Hello!".to_string();         //String object
   let name2 = name1.replace("Hello","Howdy");    //find and replace
   println!("{}",name2);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

Howdy TutorialsPoint , Howdy!

그림 : as_str ()

그만큼 as_str() 함수는 전체 문자열을 포함하는 문자열 슬라이스를 추출합니다.

fn main() {
   let example_string = String::from("example_string");
   print_literal(example_string.as_str());
}
fn print_literal(data:&str ){
   println!("displaying string literal {}",data);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

displaying string literal example_string

그림 : push ()

그만큼 push() 함수는이 문자열의 끝에 주어진 문자를 추가합니다.

fn main(){
   let mut company = "Tutorial".to_string();
   company.push('s');
   println!("{}",company);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

Tutorials

그림 : push_str ()

그만큼 push_str() 함수는 주어진 문자열 조각을 문자열 끝에 추가합니다.

fn main(){
   let mut company = "Tutorials".to_string();
   company.push_str(" Point");
   println!("{}",company);
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

Tutorials Point

그림 : len ()

그만큼 len() 함수는 문자열의 총 문자 수 (공백 포함)를 반환합니다.

fn main() {
   let fullname = " Tutorials Point";
   println!("length is {}",fullname.len());
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

length is 20

그림 : trim ()

trim () 함수는 문자열에서 선행 및 후행 공백을 제거합니다. 이 함수는 인라인 공백을 제거하지 않습니다.

fn main() {
   let fullname = " Tutorials Point \r\n";
   println!("Before trim ");
   println!("length is {}",fullname.len());
   println!();
   println!("After trim ");
   println!("length is {}",fullname.trim().len());
}

산출

위의 프로그램은 다음과 같은 출력을 생성합니다-

Before trim
length is 24

After trim
length is 15

그림 : split_whitespace ()

그만큼 split_whitespace()입력 문자열을 다른 문자열로 분할합니다. 반복자를 반환하므로 아래와 같이 토큰을 반복합니다.

fn main(){
   let msg = "Tutorials Point has good t
   utorials".to_string();
   let mut i = 1;
   
   for token in msg.split_whitespace(){
      println!("token {} {}",i,token);
      i+=1;
   }
}

산출

token 1 Tutorials
token 2 Point
token 3 has
token 4 good
token 5 tutorials

그림 : split () 문자열

그만큼 split() string메서드는 패턴과 일치하는 문자로 구분 된 문자열 조각의 하위 문자열에 대한 반복자를 반환합니다. split () 메서드의 한계는 나중에 사용하기 위해 결과를 저장할 수 없다는 것입니다. 그만큼collect 메소드는 split ()에 의해 반환 된 결과를 벡터로 저장하는 데 사용할 수 있습니다.

fn main() {
   let fullname = "Kannan,Sudhakaran,Tutorialspoint";

   for token in fullname.split(","){
      println!("token is {}",token);
   }

   //store in a Vector
   println!("\n");
   let tokens:Vec<&str>= fullname.split(",").collect();
   println!("firstName is {}",tokens[0]);
   println!("lastname is {}",tokens[1]);
   println!("company is {}",tokens[2]);
}

위의 예는 문자열을 분할합니다. fullname, 쉼표를 만날 때마다 (,).

산출

token is Kannan
token is Sudhakaran
token is Tutorialspoint

firstName is Kannan
lastname is Sudhakaran
company is Tutorialspoint

그림 : chars ()

문자열의 개별 문자는 chars 메서드를 사용하여 액세스 할 수 있습니다. 이것을 이해하기위한 예를 고려해 보겠습니다.

fn main(){
   let n1 = "Tutorials".to_string();

   for n in n1.chars(){
      println!("{}",n);
   }
}

산출

T
u
t
o
r
i
a
l
s

+ 연산자를 사용하여 문자열 연결

문자열 값을 다른 문자열에 추가 할 수 있습니다. 이를 연결 또는 보간이라고합니다. 문자열 연결의 결과는 새로운 문자열 객체입니다. + 연산자는 내부적으로 add 메서드를 사용합니다 . add 함수의 구문은 두 개의 매개 변수를 사용합니다. 첫 번째 매개 변수는 self – 문자열 객체 자체이고 두 번째 매개 변수는 두 번째 문자열 객체의 참조입니다. 이것은 아래에 표시됩니다-

//add function
add(self,&str)->String { 
   // returns a String object
}

그림 : 문자열 연결

fn main(){
   let n1 = "Tutorials".to_string();
   let n2 = "Point".to_string();

   let n3 = n1 + &n2; // n2 reference is passed
   println!("{}",n3);
}

출력은 다음과 같습니다.

TutorialsPoint

그림 : 유형 주조

다음 예제는 숫자를 문자열 객체로 변환하는 방법을 보여줍니다.

fn main(){
   let number = 2020;
   let number_as_string = number.to_string(); 
   
   // convert number to string
   println!("{}",number_as_string);
   println!("{}",number_as_string=="2020");
}

출력은 다음과 같습니다.

2020
true

그림 : 포맷! 매크로

String 객체에 함께 추가하는 또 다른 방법은 format이라는 매크로 함수를 사용하는 것입니다. 포맷의 사용! 아래와 같습니다.

fn main(){
   let n1 = "Tutorials".to_string();
   let n2 = "Point".to_string();
   let n3 = format!("{} {}",n1,n2);
   println!("{}",n3);
}

출력은 다음과 같습니다.

Tutorials Point

연산자는 데이터에 대해 수행 될 일부 기능을 정의합니다. 연산자가 작동하는 데이터를 피연산자라고합니다. 다음 식을 고려하십시오-

7 + 5 = 12

여기서 7, 5 및 12 값은 피연산자이고 + 및 =는 연산자입니다.

Rust의 주요 연산자는 다음과 같이 분류 할 수 있습니다.

  • Arithmetic
  • Bitwise
  • Comparison
  • Logical
  • Bitwise
  • Conditional

산술 연산자

변수 a와 b의 값이 각각 10과 5라고 가정합니다.

예시보기

Sr. 아니요 운영자 기술
1 + (더하기) 피연산자의 합계를 반환합니다. a + b는 15입니다.
2 -(빼기) 값의 차이를 반환합니다. ab는 5
* (곱하기) 값의 곱을 반환합니다. a * b는 50입니다.
4 / (나누기) 나눗셈 연산을 수행하고 몫을 반환합니다. a / b는 2입니다.
5 % (모듈러스) 나누기 연산을 수행하고 나머지를 반환합니다. a % b는 0입니다.

NOTE − ++ 및-연산자는 Rust에서 지원되지 않습니다.

관계 연산자

관계 연산자는 두 엔티티 간의 관계 유형을 테스트하거나 정의합니다. 관계 연산자는 둘 이상의 값을 비교하는 데 사용됩니다. 관계 연산자는 부울 값 (true 또는 false)을 반환합니다.

A의 값이 10이고 B가 20이라고 가정합니다.

예시보기

Sr. 아니요 운영자 기술
1 > 보다 큰 (A> B)는 False입니다.
2 < 보다 작음 (A <B)는 참입니다
> = 크거나 같음 (A> = B)는 False입니다.
4 <= 작거나 같음 (A <= B)는 참입니다
5 == 평등 (A == B)는 거짓입니다.
6 ! = 같지 않음 (A! = B)는 참입니다

논리 연산자

논리 연산자는 둘 이상의 조건을 결합하는 데 사용됩니다. 논리 연산자도 부울 값을 반환합니다. 변수 A의 값이 10이고 B가 20이라고 가정합니다.

예시보기

Sr. 아니요 운영자 기술
1 && (그리고) 연산자는 지정된 모든 표현식이 true를 반환하는 경우에만 true를 반환합니다. (A> 10 && B> 10)은 거짓입니다.
2 || (또는) 연산자는 지정된 표현식 중 하나 이상이 true를 반환하면 true를 반환합니다. (A> 10 || B> 10)은 참
! (아니) 연산자는 식 결과의 역을 반환합니다. 예 :! (> 5)는 false를 반환합니다. ! (A> 10)은 True입니다.

비트 연산자

변수 A = 2 및 B = 3이라고 가정합니다.

예시보기

Sr. 아니요 운영자 기술
1 & (비트 AND) 정수 인수의 각 비트에 대해 부울 AND 연산을 수행합니다. (A & B)는 2입니다.
2 | (BitWise OR) 정수 인수의 각 비트에 대해 부울 OR 연산을 수행합니다. (A | B)는 3입니다.
^ (비트 XOR) 정수 인수의 각 비트에 대해 부울 배타적 OR 연산을 수행합니다. 배타적 OR은 피연산자 1이 참이거나 피연산자 2가 참이지만 둘다는 아니라는 것을 의미합니다. (A ^ B)는 1입니다.
4 ! (비트가 아닙니다) 단항 연산자이며 피연산자의 모든 비트를 반전하여 작동합니다. (! B)는 -4입니다.
5 << (왼쪽 이동) 첫 번째 피연산자의 모든 비트를 두 번째 피연산자에 지정된 자릿수만큼 왼쪽으로 이동합니다. 새 비트는 0으로 채워집니다. 값을 한 위치 왼쪽으로 이동하는 것은 2를 곱하는 것과 같고, 두 위치를 이동하는 것은 4를 곱하는 것과 같습니다. (A << 1)은 4입니다.
6 >> (오른쪽 이동) 이진 오른쪽 시프트 연산자. 왼쪽 피연산자의 값은 오른쪽 피연산자가 지정한 비트 수만큼 오른쪽으로 이동합니다. (A >> 1)은 1입니다.
7 >>> (0으로 오른쪽 시프트) 이 연산자는 >> 연산자와 비슷하지만 왼쪽으로 이동 한 비트가 항상 0이라는 점이 다릅니다. (A >>> 1)은 1입니다.

의사 결정 구조는 프로그래머가 조건이 참인 경우 실행될 명령문 또는 명령문과 함께 프로그램에서 평가하거나 테스트 할 하나 이상의 조건을 지정하고 선택적으로 조건은 거짓으로 결정됩니다.

아래는 대부분의 프로그래밍 언어에서 발견되는 일반적인 의사 결정 구조의 일반적인 형태입니다.

Sr. 아니요 성명 및 설명
1

if statement

경우 문은 하나 개 이상의 문장 다음에 부울 식으로 구성되어 있습니다.

2

if...else statement

경우 문이 옵션 다음에 할 수있는 다른 부울 표현식이 거짓 일 때 실행 문.

else...if and nested ifstatement

if 또는 else if 문을 다른 if 또는 else if 문 안에 사용할 수 있습니다 .

4

match statement

매치 문은 변수가 값 목록에 대해 테스트 할 수 있습니다.

If 문

경우 ... 다른 구조 평가하여 코드 블록 전에 조건이 실행된다.

통사론

if boolean_expression {
   // statement(s) will execute if the boolean expression is true
}

부울 표현식이 true로 평가되면 if 문 내부의 코드 블록이 실행됩니다. 부울 표현식이 false로 평가되면 if 문 끝 (닫는 중괄호 뒤) 뒤의 첫 번째 코드 집합이 실행됩니다.

fn main(){
   let num:i32 = 5;
   if num > 0 {
      println!("number is positive") ;
   }
}

위의 예는 인쇄됩니다 number is positive if 블록이 지정한 조건이 참인 경우.

if else statement

An if can be followed by an optional else block. The else block will execute if the Boolean expression tested by the if statement evaluates to false.

Syntax

if boolean_expression {
   // statement(s) will execute if the boolean expression is true
} else {
   // statement(s) will execute if the boolean expression is false
}

FlowChart

The if block guards the conditional expression. The block associated with the if statement is executed if the Boolean expression evaluates to true.

The if block may be followed by an optional else statement. The instruction block associated with the else block is executed if the expression evaluates to false.

Illustration - Simple if…else

fn main() {
   let num = 12;
   if num % 2==0 {
      println!("Even");
   } else {
      println!("Odd");
   }
}

The above example prints whether the value in a variable is even or odd. The if block checks the divisibility of the value by 2 to determine the same. Here is the output of the above code −

Even

Nested If

The else…if ladder is useful to test multiple conditions. The syntax is as shown below −

Syntax

if boolean_expression1 {
   //statements if the expression1 evaluates to true
} else if boolean_expression2 {
   //statements if the expression2 evaluates to true
} else {
   //statements if both expression1 and expression2 result to false
}

When using if…else…if and else statements, there are a few points to keep in mind.

  • An if can have zero or one else's and it must come after any else..if.
  • An if can have zero to many else..if and they must come before the else.
  • Once an else..if succeeds, none of the remaining else..if or else will be tested.

Example: else…if ladder

fn main() {
   let num = 2 ;
   if num > 0 {
      println!("{} is positive",num);
   } else if num < 0 {
      println!("{} is negative",num);
   } else {
      println!("{} is neither positive nor negative",num) ;
   }
}

The snippet displays whether the value is positive, negative or zero.

Output

2 is positive

Match Statement

The match statement checks if a current value is matching from a list of values, this is very much similar to the switch statement in C language. In the first place, notice that the expression following the match keyword does not have to be enclosed in parentheses.

The syntax is as shown below.

let expressionResult = match variable_expression {
   constant_expr1 => {
      //statements;
   },
   constant_expr2 => {
      //statements;
   },
   _ => {
      //default
   }
};

In the example given below, state_code is matched with a list of values MH, KL, KA, GA − if any match is found, a string value is returned to variable state. If no match is found, the default case _ matches and value Unkown is returned.

fn main(){
   let state_code = "MH";
   let state = match state_code {
      "MH" => {println!("Found match for MH"); "Maharashtra"},
      "KL" => "Kerala",
      "KA" => "Karnadaka",
      "GA" => "Goa",
      _ => "Unknown"
   };
   println!("State name is {}",state);
}

Output

Found match for MH
State name is Maharashtra

There may be instances, where a block of code needs to be executed repeatedly. In general, programming instructions are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

Programming languages provide various control structures that allow for more complicated execution paths.

A loop statement allows us to execute a statement or group of statements multiple times. Given below is the general form of a loop statement in most of the programming languages.

Rust provides different types of loops to handle looping requirements −

  • while
  • loop
  • for

Definite Loop

A loop the number of iterations of which is definite/fixed is termed as a definite loop. The for loop is an implementation of a definite loop.

For Loop

The for loop executes the code block for a specified number of times. It can be used to iterate over a fixed set of values, such as an array. The syntax of the for loop is as given below

Syntax

for temp_variable in lower_bound..upper_bound {
   //statements
}

An example of a for loop is as shown below

fn main(){
   for x in 1..11{ // 11 is not inclusive
      if x==5 {
         continue;
      }
      println!("x is {}",x);
   }
}

NOTE: that the variable x is only accessible within the for block.

Output

x is 1
x is 2
x is 3
x is 4
x is 6
x is 7
x is 8
x is 9
x is 10

Indefinite Loop

An indefinite loop is used when the number of iterations in a loop is indeterminate or unknown.

Indefinite loops can be implemented using −

Sr.No Name & Description
1

While

The while loop executes the instructions each time the condition specified evaluates to true

2

Loop

The loop is a while(true) indefinite loop

Illustration − for while

fn main(){
   let mut x = 0;
   while x < 10{
      x+=1;
      println!("inside loop x value is {}",x);
   }
   println!("outside loop x value is {}",x);
}

The output is as shown below −

inside loop x value is 1
inside loop x value is 2
inside loop x value is 3
inside loop x value is 4
inside loop x value is 5
inside loop x value is 6
inside loop x value is 7
inside loop x value is 8
inside loop x value is 9
inside loop x value is 10
outside loop x value is 10

Illustration −loop

fn main(){
   //while true

   let mut x = 0;
   loop {
      x+=1;
      println!("x={}",x);

      if x==15 {
         break;
      }
   }
}

그만큼 break문은 구문에서 제어를 가져 오는 데 사용됩니다. 루프에서 break를 사용하면 프로그램이 루프를 종료합니다.

산출

x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x=10
x=11
x=12
x=13
x=14
x=15

계속 진술

continue 문은 현재 반복의 후속 문을 건너 뛰고 제어를 루프의 시작 부분으로 되돌립니다. break 문과 달리 continue는 루프를 종료하지 않습니다. 현재 반복을 종료하고 후속 반복을 시작합니다.

continue 문의 예가 ​​아래에 나와 있습니다.

fn main() {

   let mut count = 0;

   for num in 0..21 {
      if num % 2==0 {
         continue;
      }
      count+=1;
   }
   println! (" The count of odd values between 0 and 20 is: {} ",count);
   //outputs 10
}

위의 예는 0과 20 사이의 짝수 값을 표시합니다. 루프는 숫자가 짝수이면 현재 반복을 종료합니다. 이는 continue 문을 사용하여 수행됩니다.

0에서 20 사이의 홀수 값 개수는 10입니다.

함수는 읽기, 유지 관리 및 재사용 가능한 코드의 구성 요소입니다. 함수는 특정 작업을 수행하는 일련의 명령문입니다. 함수는 프로그램을 논리적 코드 블록으로 구성합니다. 정의되면 코드에 액세스하기 위해 함수를 호출 할 수 있습니다. 이렇게하면 코드를 재사용 할 수 있습니다. 또한 함수를 사용하면 프로그램 코드를 쉽게 읽고 유지할 수 있습니다.

함수 선언은 함수의 이름, 반환 유형 및 매개 변수에 대해 컴파일러에 알려줍니다. 함수 정의는 함수의 실제 본문을 제공합니다.

Sr. 아니요 기능 및 설명
1

Defining a function

TA 기능 정의는 특정 작업이 수행되는 내용과 방법을 지정합니다.

2

Calling or invoking a Function

실행하려면 함수를 호출해야합니다.

Returning Functions

함수는 컨트롤과 함께 값을 호출자에게 반환 할 수도 있습니다.

4

Parameterized Function

매개 변수는 함수에 값을 전달하는 메커니즘입니다.

함수 정의

함수 정의는 특정 작업이 수행되는 내용과 방법을 지정합니다. 함수를 사용하기 전에 정의해야합니다. 함수 본문에는 함수에서 실행해야하는 코드가 포함되어 있습니다. 함수 이름 지정 규칙은 변수 이름 지정 규칙과 유사합니다. 함수는fn예어. 표준 함수를 정의하는 구문은 다음과 같습니다.

통사론

fn function_name(param1,param2..paramN) {
   // function body
}

함수 선언은 선택적으로 매개 변수 / 인수를 포함 할 수 있습니다. 매개 변수는 함수에 값을 전달하는 데 사용됩니다.

예-간단한 함수 정의

//Defining a function
fn fn_hello(){
   println!("hello from function fn_hello ");
}

함수 호출

실행하려면 함수를 호출해야합니다. 이 프로세스는function invocation. 매개 변수 값은 함수가 호출 될 때 전달되어야합니다. 다른 함수를 호출하는 함수를caller function.

통사론

function_name(val1,val2,valN)

예 : 함수 호출

fn main(){
   //calling a function
   fn_hello();
}

여기서 main () 은 호출자 함수입니다.

삽화

다음 예제는 함수를 정의합니다. fn_hello(). 이 함수는 콘솔에 메시지를 인쇄합니다. 그만큼main()함수는 fn_hello () 함수를 호출합니다 .

fn main(){
   //calling a function
   fn_hello();
}
//Defining a function
fn fn_hello(){
   println!("hello from function fn_hello ");
}

산출

hello from function fn_hello

함수에서 값 반환

함수는 컨트롤과 함께 값을 호출자에게 반환 할 수도 있습니다. 이러한 함수를 반환 함수라고합니다.

통사론

다음 구문 중 하나를 사용하여 반환 유형이있는 함수를 정의 할 수 있습니다.

반품 명세서 포함

// Syntax1
fn function_name() -> return_type {
   //statements
   return value;
}

return 문이없는 속기 구문

//Syntax2
fn function_name() -> return_type {
   value //no semicolon means this value is returned
}

삽화

fn main(){
   println!("pi value is {}",get_pi());
}
fn get_pi()->f64 {
   22.0/7.0
}

산출

pi value is 3.142857142857143

매개 변수가있는 기능

매개 변수는 함수에 값을 전달하는 메커니즘입니다. 매개 변수는 함수 시그니처의 일부를 구성합니다. 매개 변수 값은 호출 중에 함수에 전달됩니다. 명시 적으로 지정하지 않는 한 함수에 전달되는 값의 수는 정의 된 매개 변수의 수와 일치해야합니다.

매개 변수는 다음 기술 중 하나를 사용하여 함수에 전달할 수 있습니다.

가치로 전달

메소드가 호출되면 각 값 매개 변수에 대해 새 저장 위치가 생성됩니다. 실제 매개 변수의 값이 여기에 복사됩니다. 따라서 호출 된 메서드 내부의 매개 변수에 대한 변경 사항은 인수에 영향을주지 않습니다.

다음 예제는 처음에 5 인 변수 no를 선언합니다. 변수는 매개 변수 (값 기준)로 mutate_no_to_zero()functionnction, 값을 0으로 변경합니다. 컨트롤이 메인 메소드로 돌아갈 때 함수 호출 후 값은 동일합니다.

fn main(){
   let no:i32 = 5;
   mutate_no_to_zero(no);
   println!("The value of no is:{}",no);
}

fn mutate_no_to_zero(mut param_no: i32) {
   param_no = param_no*0;
   println!("param_no value is :{}",param_no);
}

산출

param_no value is :0
The value of no is:5

참조로 통과

매개 변수를 참조로 전달하면 값 매개 변수와 달리 이러한 매개 변수에 대해 새 저장 위치가 생성되지 않습니다. 참조 매개 변수는 메소드에 제공되는 실제 매개 변수와 동일한 메모리 위치를 나타냅니다. 매개 변수 값은 변수 이름에 접두사를 붙여 참조로 전달할 수 있습니다.& .

아래 주어진 예에서 변수 no 는 처음에 5입니다. 변수 no에 대한 참조는mutate_no_to_zero()함수. 이 함수는 원래 변수에서 작동합니다. 함수 호출 후 제어가 메인 메소드로 돌아 오면 원래 변수의 값은 0이됩니다.

fn main() {
   let mut no:i32 = 5;
   mutate_no_to_zero(&mut no);
   println!("The value of no is:{}",no);
}
fn mutate_no_to_zero(param_no:&mut i32){
   *param_no = 0; //de reference
}

* 연산자는 변수가 메모리 위치에 저장된 값에 액세스하는 데 사용됩니다. param_no에 중점을 두다. 이를 역 참조라고도합니다.

출력은-

The value of no is 0.

함수에 문자열 전달

의 main () 함수에 전달 캐릭터 오브젝트 디스플레이 () 함수.

fn main(){
   let name:String = String::from("TutorialsPoint");
   display(name); 
   //cannot access name after display
}
fn display(param_name:String){
   println!("param_name value is :{}",param_name);
}

산출

param_name value is :TutorialsPoint

튜플은 복합 데이터 유형입니다. 스칼라 유형은 한 가지 유형의 데이터 만 저장할 수 있습니다. 예를 들어, i32 변수는 단일 정수 값만 저장할 수 있습니다. 복합 유형에서는 한 번에 둘 이상의 값을 저장할 수 있으며 다른 유형일 수 있습니다.

튜플은 길이가 고정되어 있습니다. 일단 선언되면 크기가 늘어나거나 줄어들 수 없습니다. 튜플 인덱스는0.

통사론

//Syntax1
let tuple_name:(data_type1,data_type2,data_type3) = (value1,value2,value3);

//Syntax2
let tuple_name = (value1,value2,value3);

삽화

다음 예제는 튜플의 값을 표시합니다.

fn main() {
   let tuple:(i32,f64,u8) = (-325,4.9,22);
   println!("{:?}",tuple);
}

에 println은! ( "{}"튜플) 구문 튜플 값을 표시 할 수 없다. 튜플이 복합 유형이기 때문입니다. 사용 에 println를! ( '{:?} ", tuple_name) 튜플의 값을 인쇄하는 구문.

산출

(-325, 4.9, 22)

삽화

다음 예제는 튜플의 개별 값을 인쇄합니다.

fn main() {
   let tuple:(i32,f64,u8) = (-325,4.9,22);
   println!("integer is :{:?}",tuple.0);
   println!("float is :{:?}",tuple.1);
   println!("unsigned integer is :{:?}",tuple.2);
}

산출

integer is :-325
float is :4.9
unsigned integer is :2

삽화

다음 예제는 튜플을 매개 변수로 함수에 전달합니다. 튜플은 값으로 함수에 전달됩니다.

fn main(){
   let b:(i32,bool,f64) = (110,true,10.9);
   print(b);
}
//pass the tuple as a parameter

fn print(x:(i32,bool,f64)){
   println!("Inside print method");
   println!("{:?}",x);
}

산출

Inside print method
(110, true, 10.9)

파괴

Destructing assignment는 튜플의 값을 푸는 녹의 특징입니다. 이것은 별개의 변수에 튜플을 할당함으로써 가능합니다.

다음 예를 고려하십시오-

fn main(){
   let b:(i32,bool,f64) = (30,true,7.9);
   print(b);
}
fn print(x:(i32,bool,f64)){
   println!("Inside print method");
   let (age,is_male,cgpa) = x; //assigns a tuple to 
   distinct variables
   println!("Age is {} , isMale? {},cgpa is 
   {}",age,is_male,cgpa);
}

변수 x 는 let 문에 할당 된 튜플입니다. 각 변수-age, is_male 및 cgpa는 튜플에 해당 값을 포함합니다.

산출

Inside print method
Age is 30 , isMale? true,cgpa is 7.9

이 장에서는 어레이 및 이와 관련된 다양한 기능에 대해 알아 봅니다. 배열에 대해 배우기 전에 배열이 변수와 어떻게 다른지 살펴 보겠습니다.

변수에는 다음과 같은 제한이 있습니다.

  • 변수는 본질적으로 스칼라입니다. 즉, 변수 선언은 한 번에 하나의 값만 포함 할 수 있습니다. 이것은 프로그램에 n 개의 값을 저장하기 위해서는 변수 선언이 필요하다는 것을 의미합니다. 따라서 더 큰 값 모음을 저장해야 할 때 변수를 사용할 수 없습니다.

  • 프로그램의 변수는 임의의 순서로 메모리가 할당되므로 선언 된 순서대로 값을 검색 / 읽기가 어렵습니다.

배열은 값의 동종 모음입니다. 간단히 말해서 배열은 동일한 데이터 유형의 값 모음입니다.

어레이의 특징

배열의 기능은 다음과 같습니다.

  • 배열 선언은 순차 메모리 블록을 할당합니다.

  • 배열은 정적입니다. 즉, 일단 초기화 된 배열은 크기를 조정할 수 없습니다.

  • 각 메모리 블록은 배열 요소를 나타냅니다.

  • 배열 요소는 요소의 첨자 / 인덱스라고하는 고유 한 정수로 식별됩니다.

  • 배열 요소를 채우는 것을 배열 초기화라고합니다.

  • 배열 요소 값은 업데이트하거나 수정할 수 있지만 삭제할 수는 없습니다.

배열 선언 및 초기화

Rust에서 배열을 선언하고 초기화하려면 아래에 주어진 구문을 사용하십시오.

통사론

//Syntax1
let variable_name = [value1,value2,value3];

//Syntax2
let variable_name:[dataType;size] = [value1,value2,value3];

//Syntax3
let variable_name:[dataType;size] = [default_value_for_elements,size];

첫 번째 구문에서 배열의 유형은 초기화 중에 배열의 첫 번째 요소의 데이터 유형에서 유추됩니다.

그림 : 단순 배열

다음 예제는 배열의 크기와 데이터 유형을 명시 적으로 지정합니다. println! () 함수 의 {:?} 구문은 배열의 모든 값을 인쇄하는 데 사용됩니다. 렌 () 함수는 상기 어레이의 크기를 계산하는 데 사용된다.

fn main(){
   let arr:[i32;4] = [10,20,30,40];
   println!("array is {:?}",arr);
   println!("array size is :{}",arr.len());
}

산출

array is [10, 20, 30, 40]
array size is :4

그림 : 데이터 유형이없는 배열

다음 프로그램은 4 개 요소의 배열을 선언합니다. 데이터 유형은 변수 선언 중에 명시 적으로 지정되지 않습니다. 이 경우 배열은 정수 유형이됩니다. 렌 () 함수는 상기 어레이의 크기를 계산하는 데 사용된다.

fn main(){
   let arr = [10,20,30,40];
   println!("array is {:?}",arr);
   println!("array size is :{}",arr.len());
}

산출

array is [10, 20, 30, 40]
array size is :4

그림 : 기본값

다음 예제에서는 배열을 만들고 기본값 -1을 사용하여 모든 요소를 ​​초기화합니다 .

fn main() {
   let arr:[i32;4] = [-1;4];
   println!("array is {:?}",arr);
   println!("array size is :{}",arr.len());
}

산출

array is [-1, -1, -1, -1]
array size is :4

그림 : for 루프가있는 배열

다음 예제는 배열을 반복하고 인덱스와 해당 값을 인쇄합니다. 루프는 인덱스 0에서 4 (마지막 배열 요소의 인덱스)에서 값을 검색합니다.

fn main(){
   let arr:[i32;4] = [10,20,30,40];
   println!("array is {:?}",arr);
   println!("array size is :{}",arr.len());

   for index in 0..4 {
      println!("index is: {} & value is : {}",index,arr[index]);
   }
}

산출

array is [10, 20, 30, 40]
array size is :4
index is: 0 & value is : 10
index is: 1 & value is : 20
index is: 2 & value is : 30
index is: 3 & value is : 40

그림 : iter () 함수 사용

iter () 함수는 배열의 모든 요소 값을 가져옵니다.

fn main(){

let arr:[i32;4] = [10,20,30,40];
   println!("array is {:?}",arr);
   println!("array size is :{}",arr.len());

   for val in arr.iter(){
      println!("value is :{}",val);
   }
}

산출

array is [10, 20, 30, 40]
array size is :4
value is :10
value is :20
value is :30
value is :40

그림 : 가변 배열

MUT의 키워드는 변경 가능한 배열을 선언 할 수 있습니다. 다음 예제는 가변 배열을 선언하고 두 번째 배열 요소의 값을 수정합니다.

fn main(){
   let mut arr:[i32;4] = [10,20,30,40];
   arr[1] = 0;
   println!("{:?}",arr);
}

산출

[10, 0, 30, 40]

배열을 매개 변수로 함수에 전달

배열은 값 또는 함수 참조로 전달할 수 있습니다.

그림 : 가치로 전달

fn main() {
   let arr = [10,20,30];
   update(arr);

   print!("Inside main {:?}",arr);
}
fn update(mut arr:[i32;3]){
   for i in 0..3 {
      arr[i] = 0;
   }
   println!("Inside update {:?}",arr);
}

산출

Inside update [0, 0, 0]
Inside main [10, 20, 30]

그림 : 참조 통과

fn main() {
   let mut arr = [10,20,30];
   update(&mut arr);
   print!("Inside main {:?}",arr);
}
fn update(arr:&mut [i32;3]){
   for i in 0..3 {
      arr[i] = 0;
   }
   println!("Inside update {:?}",arr);
}

산출

Inside update [0, 0, 0]
Inside main [0, 0, 0]

배열 선언 및 상수

배열 선언과 상수를 이해하기 위해 아래에 주어진 예를 고려해 보겠습니다.

fn main() {
   let N: usize = 20;
   let arr = [0; N]; //Error: non-constant used with constant
   print!("{}",arr[10])
}

컴파일러에서 예외가 발생합니다. 이는 컴파일 타임에 배열의 길이를 알아야하기 때문입니다. 여기서 변수 "N"의 값은 런타임에 결정됩니다. 즉, 변수는 배열의 크기를 정의하는 데 사용할 수 없습니다.

그러나 다음 프로그램은 유효합니다-

fn main() {
   const N: usize = 20; 
   // pointer sized
   let arr = [0; N];

   print!("{}",arr[10])
}

const 키워드가 접두사로 붙은 식별자의 값은 컴파일 타임에 정의되며 런타임에 변경할 수 없습니다. usize는 포인터 크기이므로 실제 크기는 프로그램을 컴파일하는 아키텍처에 따라 다릅니다.

프로그램의 메모리는 다음에 할당 할 수 있습니다.

  • Stack
  • Heap

스택

스택은 마지막 선입 선출 순서를 따릅니다. Stack은 컴파일 타임에 크기가 알려진 데이터 값을 저장합니다. 예를 들어, 고정 크기 i32의 변수는 스택 할당 후보입니다. 크기는 컴파일 타임에 알려져 있습니다. 크기가 고정되어 있으므로 모든 스칼라 유형을 스택에 저장할 수 있습니다.

런타임에 값이 할당되는 문자열의 예를 고려하십시오. 이러한 문자열의 정확한 크기는 컴파일 타임에 확인할 수 없습니다. 따라서 스택 할당 후보가 아니라 힙 할당 후보입니다.

더미

힙 메모리는 컴파일 타임에 크기를 알 수없는 데이터 값을 저장합니다. 동적 데이터를 저장하는 데 사용됩니다. 간단히 말해서 힙 메모리는 프로그램의 수명주기 동안 변경 될 수있는 데이터 값에 할당됩니다. 힙은 스택과 비교할 때 덜 구성되는 메모리 영역입니다.

소유권이란 무엇입니까?

Rust의 각 값에는 다음과 같은 변수가 있습니다. owner가치의. Rust에 저장된 모든 데이터에는 소유자가 있습니다. 예를 들어 -let age = 30 구문 에서 age 는 값 30 의 소유자입니다 .

  • 각 데이터는 한 번에 한 명의 소유자 만 가질 수 있습니다.

  • 두 변수는 동일한 메모리 위치를 가리킬 수 없습니다. 변수는 항상 다른 메모리 위치를 가리 킵니다.

소유권 이전

가치의 소유권은 다음에 의해 양도 될 수 있습니다.

  • 한 변수의 값을 다른 변수에 할당합니다.

  • 함수에 값을 전달합니다.

  • 함수에서 값을 반환합니다.

한 변수의 값을 다른 변수에 할당

언어로서의 Rust의 주요 판매 포인트는 메모리 안전성입니다. 누가 무엇을 언제 사용할 수 있는지에 대한 엄격한 제어를 통해 메모리 안전성이 달성됩니다.

다음 스 니펫을 고려하십시오-

fn main(){
   let v = vec![1,2,3]; 
   // vector v owns the object in heap

   //only a single variable owns the heap memory at any given time
   let v2 = v; 
   // here two variables owns heap value,
   //two pointers to the same content is not allowed in rust

   //Rust is very smart in terms of memory access ,so it detects a race condition
   //as two variables point to same heap

   println!("{:?}",v);
}

위의 예는 벡터 v를 선언합니다. 소유권 개념은 하나의 변수 만 리소스에 바인딩된다는 것입니다. v 자원에 바인딩하거나 v2리소스에 바인딩합니다. 위의 예에서는 오류가 발생합니다- 이동 된 값 사용 :`v` . 이는 리소스의 소유권이 v2로 이전되기 때문입니다. 이는 소유권이 v에서 v2 (v2 = v)로 이동되고 v는 이동 후 무효화됨을 의미합니다.

함수에 값 전달

값의 소유권은 힙의 객체를 클로저 또는 함수로 전달할 때도 변경됩니다.

fn main(){
   let v = vec![1,2,3];     // vector v owns the object in heap
   let v2 = v;              // moves ownership to v2
   display(v2);             // v2 is moved to display and v2 is invalidated
   println!("In main {:?}",v2);    //v2 is No longer usable here
}
fn display(v:Vec<i32>){
   println!("inside display {:?}",v);
}

함수에서 값 반환

함수 실행이 완료되면 함수에 전달 된 소유권이 무효화됩니다. 이에 대한 한 가지 해결 방법은 함수가 소유 한 개체를 호출자에게 반환하도록하는 것입니다.

fn main(){
   let v = vec![1,2,3];       // vector v owns the object in heap
   let v2 = v;                // moves ownership to v2
   let v2_return = display(v2);    
   println!("In main {:?}",v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> { 
   // returning same vector
   println!("inside display {:?}",v);
}

소유권 및 기본 유형

기본 유형의 경우 한 변수의 내용이 다른 변수로 복사됩니다. 따라서 소유권 이전이 발생하지 않습니다. 이는 기본 변수가 객체보다 적은 자원을 필요로하기 때문입니다. 다음 예를 고려하십시오-

fn main(){
   let u1 = 10;
   let u2 = u1;  // u1 value copied(not moved) to u2

   println!("u1 = {}",u1);
}

출력은 – 10입니다.

변수의 소유권을 다른 함수에 전달한 다음 소유권을 반환하는 것은 매우 불편합니다. Rust는 가치의 소유권이 일시적으로 엔티티로 이전 된 다음 원래 소유자 엔티티로 반환되는 차용 개념을 지원합니다.

다음을 고려하십시오-

fn main(){
   // a list of nos
   let v = vec![10,20,30];
   print_vector(v);
   println!("{}",v[0]); // this line gives error
}
fn print_vector(x:Vec<i32>){
   println!("Inside print_vector function {:?}",x);
}

주 함수는 print_vector () 함수를 호출합니다 . 벡터는이 함수에 매개 변수로 전달됩니다. 벡터의 소유권도 main () 에서 print_vector () 함수로 전달됩니다 . 위의 코드는 main () 함수가 벡터 v 에 액세스하려고 할 때 아래와 같이 오류가 발생 합니다 .

|  print_vector(v);
|     - value moved here
|  println!("{}",v[0]);
|     ^ value used here after move

이는 소유권이 다른 함수로 이전되면 원래 소유했던 함수에서 더 이상 변수 또는 값을 사용할 수 없기 때문입니다.

차입이란 무엇입니까?

함수가 변수 / 값에 대한 제어를 일시적으로 다른 함수로 이전하는 경우이를 차용이라고합니다. 이것은 변수에 대한 참조를 전달하여 수행됩니다.(& var_name)변수 / 값 자체를 함수에 전달하는 대신 컨트롤이 전달 된 함수가 실행을 완료 한 후 변수 / 값의 소유권이 변수의 원래 소유자에게 이전됩니다.

fn main(){
   // a list of nos
   let v = vec![10,20,30];
   print_vector(&v); // passing reference
   println!("Printing the value from main() v[0]={}",v[0]);
}
fn print_vector(x:&Vec<i32>){
   println!("Inside print_vector function {:?}",x);
}

산출

Inside print_vector function [10, 20, 30]
Printing the value from main() v[0] = 10

가변 참조

함수는 그러한 리소스에 대한 변경 가능한 참조 를 사용하여 빌린 리소스를 수정할 수 있습니다 . 변경 가능한 참조는&mut. 변경 가능한 참조는 변경 가능한 변수에서만 작동 할 수 있습니다.

그림 : 정수 참조 변형

fn add_one(e: &mut i32) {
   *e+= 1;
}
fn main() {
   let mut i = 3;
   add_one(&mut i);
   println!("{}", i);
}

의 main () 함수가 변경 가능한 정수 변수 선언 I를 상기의 I의 가변 기준을 통과add_one(). add_one ()은 변수 i의 값을 1 씩 증가시킵니다.

그림 : 문자열 참조 변형

fn main() {
   let mut name:String = String::from("TutorialsPoint");
   display(&mut name); 
   //pass a mutable reference of name
   println!("The value of name after modification is:{}",name);
}
fn display(param_name:&mut String){
   println!("param_name value is :{}",param_name);
   param_name.push_str(" Rocks"); 
   //Modify the actual string,name
}

의 main () 함수는 변수의 가변 기준 패스 이름 받는 디스플레이 () 함수. 표시 기능은 원래 이름 변수에 추가 문자열을 추가합니다 .

산출

param_name value is :TutorialsPoint
The value of name after modification is:TutorialsPoint Rocks

슬라이스는 메모리 블록에 대한 포인터입니다. 슬라이스는 인접한 메모리 블록에 저장된 데이터 부분에 액세스하는 데 사용할 수 있습니다. 배열, 벡터 및 문자열과 같은 데이터 구조와 함께 사용할 수 있습니다. 슬라이스는 인덱스 번호를 사용하여 데이터 부분에 액세스합니다. 슬라이스의 크기는 런타임에 결정됩니다.

슬라이스는 실제 데이터에 대한 포인터입니다. 차용이라고도하는 함수에 대한 참조로 전달됩니다.

예를 들어 슬라이스를 사용하여 문자열 값의 일부를 가져올 수 있습니다. 슬라이스 된 문자열은 실제 문자열 개체에 대한 포인터입니다. 따라서 문자열의 시작 및 끝 인덱스를 지정해야합니다. 인덱스는 배열과 마찬가지로 0부터 시작합니다.

통사론

let sliced_value = &data_structure[start_index..end_index]

최소 인덱스 값은 0이고 최대 인덱스 값은 데이터 구조의 크기입니다. end_index는 최종 문자열에 포함되지 않습니다.

아래 다이어그램 은 9 개의 문자로 구성된 샘플 문자열 Tutorials를 보여줍니다 . 첫 번째 문자의 인덱스는 0이고 마지막 문자의 인덱스는 8입니다.

다음 코드는 문자열에서 5 자 (인덱스 4부터 시작)를 가져옵니다.

fn main() {
   let n1 = "Tutorials".to_string();
   println!("length of string is {}",n1.len());
   let c1 = &n1[4..9]; 
   
   // fetches characters at 4,5,6,7, and 8 indexes
   println!("{}",c1);
}

산출

length of string is 9
rials

스톡 콘텐츠-정수 배열 슬라이스

main () 함수는 5 개의 요소가있는 배열을 선언합니다. 그것은use_slice()함수를 사용하고 세 요소의 슬라이스 (데이터 배열을 가리킴)를 전달합니다. 슬라이스는 참조로 전달됩니다. use_slice () 함수는 슬라이스 값과 길이를 출력합니다.

fn main(){
   let data = [10,20,30,40,50];
   use_slice(&data[1..4]);
   //this is effectively borrowing elements for a while
}
fn use_slice(slice:&[i32]) { 
   // is taking a slice or borrowing a part of an array of i32s
   println!("length of slice is {:?}",slice.len());
   println!("{:?}",slice);
}

산출

length of slice is 3
[20, 30, 40]

가변 슬라이스

그만큼 &mut 키워드는 슬라이스를 변경 가능으로 표시하는 데 사용할 수 있습니다.

fn main(){
   let mut data = [10,20,30,40,50];
   use_slice(&mut data[1..4]);
   // passes references of 
   20, 30 and 40
   println!("{:?}",data);
}
fn use_slice(slice:&mut [i32]) {
   println!("length of slice is {:?}",slice.len());
   println!("{:?}",slice);
   slice[0] = 1010; // replaces 20 with 1010
}

산출

length of slice is 3
[20, 30, 40]
[10, 1010, 30, 40, 50]

위의 코드는 가변 슬라이스를 use_slice () 함수에 전달합니다. 이 함수는 원래 배열의 두 번째 요소를 수정합니다.

배열은 값의 동종 컬렉션을 나타내는 데 사용됩니다. 마찬가지로 구조는 Rust에서 사용할 수있는 또 다른 사용자 정의 데이터 유형으로, 다른 구조를 포함하여 다른 유형의 데이터 항목을 결합 할 수 있습니다. 구조는 데이터를 키-값 쌍으로 정의합니다.

구문-구조 선언

구조체의 키워드는 구조를 선언하는 데 사용됩니다. 구조는 정적으로 유형이 지정되므로 구조의 모든 필드는 데이터 유형과 연관되어야합니다. 구조에 대한 명명 규칙 및 규칙은 변수와 유사합니다. 구조 블록은 세미콜론으로 끝나야합니다.

struct Name_of_structure {
   field1:data_type,
   field2:data_type,
   field3:data_type
}

구문-구조 초기화

구조체를 선언 한 후 각 필드에 값을 할당해야합니다. 이것을 초기화라고합니다.

let instance_name = Name_of_structure {
   field1:value1,
   field2:value2,
   field3:value3
}; 
//NOTE the semicolon
Syntax: Accessing values in a structure
Use the dot notation to access value of a specific field.
instance_name.field1
Illustration
struct Employee {
   name:String,
   company:String,
   age:u32
}
fn main() {
   let emp1 = Employee {
      company:String::from("TutorialsPoint"),
      name:String::from("Mohtashim"),
      age:50
   };
   println!("Name is :{} company is {} age is {}",emp1.name,emp1.company,emp1.age);
}

위의 예는 이름, 회사 및 연령 유형의 세 필드가있는 구조체 Employee를 선언합니다. main ()은 구조를 초기화합니다. 그것은 println을 사용합니다! 매크로는 구조에 정의 된 필드의 값을 인쇄합니다.

산출

Name is :Mohtashim company is TutorialsPoint age is 50

구조체 인스턴스 수정

인스턴스를 수정하려면 인스턴스 변수를 변경 가능으로 표시해야합니다. 아래 예제는 Employee 라는 구조를 선언하고 초기화 하고 나중에 age 필드의 값 을 50에서 40으로 수정합니다 .

let mut emp1 = Employee {
   company:String::from("TutorialsPoint"),
   name:String::from("Mohtashim"),
   age:50
};
emp1.age = 40;
println!("Name is :{} company is {} age is 
{}",emp1.name,emp1.company,emp1.age);

산출

Name is :Mohtashim company is TutorialsPoint age is 40

함수에 구조체 전달

다음 예제는 struct의 인스턴스를 매개 변수로 전달하는 방법을 보여줍니다. 표시 메서드는 Employee 인스턴스를 매개 변수로 사용하고 세부 정보를 인쇄합니다.

fn display( emp:Employee) {
   println!("Name is :{} company is {} age is 
   {}",emp.name,emp.company,emp.age);
}

여기에 완전한 프로그램이 있습니다-

//declare a structure
struct Employee {
   name:String,
   company:String,
   age:u32
}
fn main() {
   //initialize a structure
   let emp1 = Employee {
      company:String::from("TutorialsPoint"),
      name:String::from("Mohtashim"),
      age:50
   };
   let emp2 = Employee{
      company:String::from("TutorialsPoint"),
      name:String::from("Kannan"),
      age:32
   };
   //pass emp1 and emp2 to display()
   display(emp1);
   display(emp2);
}
// fetch values of specific structure fields using the 
// operator and print it to the console
fn display( emp:Employee){
   println!("Name is :{} company is {} age is 
   {}",emp.name,emp.company,emp.age);
}

산출

Name is :Mohtashim company is TutorialsPoint age is 50
Name is :Kannan company is TutorialsPoint age is 32

함수에서 구조체 반환

두 직원의 나이를 비교하고 노인을 반환 하는 함수 who_is_elder ()를 고려해 보겠습니다 .

fn who_is_elder (emp1:Employee,emp2:Employee)->Employee {
   if emp1.age>emp2.age {
      return emp1;
   } else {
      return emp2;
   }
}

여기에 완전한 프로그램이 있습니다-

fn main() {
   //initialize structure
   let emp1 = Employee{
      company:String::from("TutorialsPoint"),
      name:String::from("Mohtashim"),
      age:50
   };
   let emp2 = Employee {
      company:String::from("TutorialsPoint"),
      name:String::from("Kannan"),
      age:32
   };
   let elder = who_is_elder(emp1,emp2);
   println!("elder is:");

   //prints details of the elder employee
   display(elder);
}
//accepts instances of employee structure and compares their age
fn who_is_elder (emp1:Employee,emp2:Employee)->Employee {
   if emp1.age>emp2.age {
      return emp1;
   } else {
      return emp2;
   }
}
//display name, comapny and age of the employee
fn display( emp:Employee) {
   println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age);
}
//declare a structure
struct Employee {
   name:String,
   company:String,
   age:u32
}

산출

elder is:
Name is :Mohtashim company is TutorialsPoint age is 50

구조 방법

메서드는 함수와 같습니다. 프로그래밍 명령어의 논리적 그룹입니다. 메소드는fn예어. 메서드의 범위는 구조 블록 내에 있습니다.

메서드는 구조 블록 외부에서 선언됩니다. 그만큼impl키워드는 구조의 컨텍스트 내에서 메소드를 정의하는 데 사용됩니다. 메서드의 첫 번째 매개 변수는 항상self, 구조의 호출 인스턴스를 나타냅니다. 메서드는 구조의 데이터 멤버에 대해 작동합니다.

메서드를 호출하려면 먼저 구조를 인스턴스화해야합니다. 구조의 인스턴스를 사용하여 메서드를 호출 할 수 있습니다.

통사론

struct My_struct {}
impl My_struct { 
   //set the method's context
   fn method_name() { 
      //define a method
   }
}

삽화

다음 예제는 widthheight 필드가 있는 구조 Rectangle 을 정의합니다 . 메서드 영역 은 구조의 컨텍스트 내에서 정의됩니다. area 메서드는 self 키워드 를 통해 구조의 필드에 액세스하고 직사각형의 면적을 계산합니다.

//define dimensions of a rectangle
struct Rectangle {
   width:u32, height:u32
}

//logic to calculate area of a rectangle
impl Rectangle {
   fn area(&self)->u32 {
      //use the . operator to fetch the value of a field via the self keyword
      self.width * self.height
   }
}

fn main() {
   // instanatiate the structure
   let small = Rectangle {
      width:10,
      height:20
   };
   //print the rectangle's area
   println!("width is {} height is {} area of Rectangle 
   is {}",small.width,small.height,small.area());
}

산출

width is 10 height is 20 area of Rectangle is 200

구조의 정적 방법

정적 메서드는 유틸리티 메서드로 사용할 수 있습니다. 이러한 메서드는 구조가 인스턴스화되기 전에도 존재합니다. 정적 메서드는 구조의 이름을 사용하여 호출되며 인스턴스없이 액세스 할 수 있습니다. 일반 메소드와 달리 정적 메소드는 & self 매개 변수를 사용 하지 않습니다 .

구문-정적 메서드 선언

함수 및 기타 메서드와 같은 정적 메서드는 선택적으로 매개 변수를 포함 할 수 있습니다.

impl Structure_Name {
   //static method that creates objects of the Point structure
   fn method_name(param1: datatype, param2: datatype) -> return_type {
      // logic goes here
   }
}

구문-정적 메서드 호출

structure_name :: 구문 정적 메소드를 액세스하기 위해 사용된다.

structure_name::method_name(v1,v2)

삽화

다음 예제에서는 getInstance 메서드를 Point 구조의 인스턴스를 만들고 반환하는 팩토리 클래스로 사용합니다 .

//declare a structure
struct Point {
   x: i32,
   y: i32,
}
impl Point {
   //static method that creates objects of the Point structure
   fn getInstance(x: i32, y: i32) -> Point {
      Point { x: x, y: y }
   }
   //display values of the structure's field
   fn display(&self){
      println!("x ={} y={}",self.x,self.y );
   }
}
fn main(){
   // Invoke the static method
   let p1 = Point::getInstance(10,20);
   p1.display();
}

산출

x =10 y=20

Rust 프로그래밍에서 가능한 변형 목록에서 값을 선택해야 할 때 열거 형 데이터 유형을 사용합니다. 열거 형은 enum 키워드를 사용하여 선언됩니다 . 다음은 enum의 구문입니다-

enum enum_name {
   variant1,
   variant2,
   variant3
}

그림 : 열거 사용

이 예제는 남성과 여성으로 변형 된 enum − GenderCategory 를 선언합니다 . 인쇄! 매크로는 열거 형의 값을 표시합니다. 컴파일러는 std :: fmt :: Debug 특성이 GenderCategory에 대해 구현되지 않음 오류를 발생 시킵니다 . 속성 # [derive (Debug)] 는이 오류를 억제하는 데 사용됩니다.

// The `derive` attribute automatically creates the implementation
// required to make this `enum` printable with `fmt::Debug`.
#[derive(Debug)]
enum GenderCategory {
   Male,Female
}
fn main() {
   let male = GenderCategory::Male;
   let female = GenderCategory::Female;

   println!("{:?}",male);
   println!("{:?}",female);
}

산출

Male
Female

구조체와 열거 형

다음 예제는 Person 구조를 정의합니다. 필드 성별GenderCategory (열거 형) 유형 이며 남성 또는 여성 을 값 으로 할당 할 수 있습니다 .

// The `derive` attribute automatically creates the 
implementation
// required to make this `enum` printable with 
`fmt::Debug`.

#[derive(Debug)]
enum GenderCategory {
   Male,Female
}

// The `derive` attribute automatically creates the implementation
// required to make this `struct` printable with `fmt::Debug`.
#[derive(Debug)]
struct Person {
   name:String,
   gender:GenderCategory
}

fn main() {
   let p1 = Person {
      name:String::from("Mohtashim"),
      gender:GenderCategory::Male
   };
   let p2 = Person {
      name:String::from("Amy"),
      gender:GenderCategory::Female
   };
   println!("{:?}",p1);
   println!("{:?}",p2);
}

이 예에서는 Person 유형의 p1p2 개체를 만들고 이러한 각 개체에 대한 속성, 이름 및 성별을 초기화합니다.

산출

Person { name: "Mohtashim", gender: Male }
Person { name: "Amy", gender: Female }

옵션 열거 형

옵션은 Rust 표준 라이브러리에 미리 정의 된 열거 형입니다. 이 열거 형에는 Some (data) 과 None의 두 가지 값이 있습니다.

통사론

enum Option<T> {
   Some(T),      //used to return a value
   None          // used to return null, as Rust doesn't support 
   the null keyword
}

여기서 유형 T 는 모든 유형의 값을 나타냅니다.

Rust는 null 키워드를 지원하지 않습니다 . 값의 어느 것도 상기에서 enumOption , NULL 값을 반환하는 함수에 의해 이용 될 수 없다. 반환 할 데이터가 있으면 함수는 Some (data)를 반환 할 수 있습니다 .

예를 들어 이것을 이해합시다.

프로그램은 반환 유형 옵션을 사용 하여 함수 is_even ()을 정의합니다 . 이 함수는 전달 된 값이 짝수인지 확인합니다. 입력이 짝수이면 true 값이 반환되고, 그렇지 않으면 함수는 None을 반환합니다 .

fn main() {
   let result = is_even(3);
   println!("{:?}",result);
   println!("{:?}",is_even(30));
}
fn is_even(no:i32)->Option<bool> {
   if no%2 == 0 {
      Some(true)
   } else {
      None
   }
}

산출

None
Some(true)

Match 문 및 열거 형

매치 문을 열거에 저장된 값을 비교하는 데 사용할 수 있습니다. 다음 예제는 CarType enum을 매개 변수로 사용 하는 print_size 함수를 정의합니다 . 이 함수는 매개 변수 값을 사전 정의 된 상수 세트와 비교하고 적절한 메시지를 표시합니다.

enum CarType {
   Hatch,
   Sedan,
   SUV
}
fn print_size(car:CarType) {
   match car {
      CarType::Hatch => {
         println!("Small sized car");
      },
      CarType::Sedan => {
         println!("medium sized car");
      },
      CarType::SUV =>{
         println!("Large sized Sports Utility car");
      }
   }
}
fn main(){
   print_size(CarType::SUV);
   print_size(CarType::Hatch);
   print_size(CarType::Sedan);
}

산출

Large sized Sports Utility car
Small sized car
medium sized car

옵션과 일치

Option 유형을 반환하는 is_even 함수 의 예는 아래와 같이 match 문으로 구현할 수도 있습니다.

fn main() {
   match is_even(5) {
      Some(data) => {
         if data==true {
            println!("Even no");
         }
      },
      None => {
         println!("not even");
      }
   }
}
fn is_even(no:i32)->Option<bool> {
   if no%2 == 0 {
      Some(true)
   } else {
      None
   }
}

산출

not even

데이터 유형과 일치 및 열거

열거 형의 각 변형에 데이터 유형을 추가 할 수 있습니다. 다음 예에서 열거 형의 Name 및 Usr_ID 변형은 각각 문자열 및 정수 유형입니다. 다음 예제는 데이터 유형이있는 열거 형과 함께 match 문을 사용하는 방법을 보여줍니다.

// The `derive` attribute automatically creates the implementation
// required to make this `enum` printable with `fmt::Debug`.
#[derive(Debug)]
enum GenderCategory {
   Name(String),Usr_ID(i32)
}
fn main() {
   let p1 = GenderCategory::Name(String::from("Mohtashim"));
   let p2 = GenderCategory::Usr_ID(100);
   println!("{:?}",p1);
   println!("{:?}",p2);

   match p1 {
      GenderCategory::Name(val)=> {
         println!("{}",val);
      }
      GenderCategory::Usr_ID(val)=> {
         println!("{}",val);
      }
   }
}

산출

Name("Mohtashim")
Usr_ID(100)
Mohtashim

논리적 코드 그룹을 모듈이라고합니다. 여러 모듈이crate. Rust 프로그램은 바이너리 크레이트 또는 라이브러리 크레이트를 포함 할 수 있습니다. 바이너리 크레이트는 main () 메서드 가있는 실행 가능한 프로젝트입니다 . 라이브러리 상자는 다른 프로젝트에서 재사용 할 수있는 구성 요소 그룹입니다. 바이너리 크레이트와 달리 라이브러리 크레이트에는 진입 점 (main () 메서드)이 없습니다. Cargo 도구는 Rust에서 상자를 관리하는 데 사용됩니다. 예를 들어 네트워크 모듈에는 네트워킹 관련 기능이 포함되어 있고 그래픽 모듈에는 그리기 관련 기능이 포함되어 있습니다. 모듈은 다른 프로그래밍 언어의 네임 스페이스와 유사합니다. crates.io 에서화물을 사용하여 타사 상자를 다운로드 할 수 있습니다 .

Sr. 아니요 용어 및 설명
1

crate

Rust의 컴파일 단위입니다. 크레이트는 바이너리 또는 라이브러리로 컴파일됩니다.

2

cargo

상자를위한 공식 Rust 패키지 관리 도구.

module

상자 내의 코드를 논리적으로 그룹화합니다.

4

crates.io

공식 Rust 패키지 레지스트리.

통사론

//public module
pub mod a_public_module {
   pub fn a_public_function() {
      //public function
   }
   fn a_private_function() {
      //private function
   }
}
//private module
mod a_private_module {
   fn a_private_function() {
   }
}

모듈은 공개 또는 비공개 일 수 있습니다. 개인 모듈의 구성 요소는 다른 모듈에서 액세스 할 수 없습니다. Rust의 모듈은 기본적으로 비공개입니다. 반대로 공용 모듈의 기능은 다른 모듈에서 액세스 할 수 있습니다. 모듈 앞에는pub공개하는 키워드입니다. 공용 모듈 내의 함수도 공용으로 만들어야합니다.

그림 : 모듈 정의

이 예제는 public 모듈 인 movies 를 정의합니다 . 모듈에는 매개 변수를 받아들이고 그 값을 인쇄 하는 함수 play () 가 포함되어 있습니다 .

pub mod movies {
   pub fn play(name:String) {
      println!("Playing movie {}",name);
   }
}
fn main(){
   movies::play("Herold and Kumar".to_string());
}

산출

Playing movie Herold and Kumar

키워드 사용

사용 키워드는 대중 모듈을 가져올 수 있습니다.

통사론

use public_module_name::function_name;

삽화

pub mod movies {
   pub fn play(name:String) {
      println!("Playing movie {}",name);
   }
}
use movies::play;
fn main(){
   play("Herold and Kumar ".to_string());
}

산출

Playing movie Herold and Kumar

중첩 모듈

모듈도 중첩 될 수 있습니다. 코미디 모듈은 중첩되는 영어 상기 중첩되는 모듈, 동영상 모듈. 아래의 예제 는 movies / english / comedy 모듈 내에서 기능 재생을 정의 합니다.

pub mod movies {
   pub mod english {
      pub mod comedy {
         pub fn play(name:String) {
            println!("Playing comedy movie {}",name);
         }
      }
   }
}
use movies::english::comedy::play; 
// importing a public module

fn main() {
   // short path syntax
   play("Herold and Kumar".to_string());
   play("The Hangover".to_string());

   //full path syntax
   movies::english::comedy::play("Airplane!".to_string());
}

산출

Playing comedy movie Herold and Kumar
Playing comedy movie The Hangover
Playing comedy movie Airplane!

그림-라이브러리 상자를 만들고 이진 상자에서 소비

라이브러리 상자를 만들어 보겠습니다. movie_lib, 모듈을 포함합니다. movies. 구축하려면movie_lib 도서관 상자, 우리는 도구를 사용할 것입니다 cargo.

1 단계-프로젝트 폴더 생성

movie-app 폴더 와 하위 폴더 movie-lib를 만듭니다. 폴더와 하위 폴더가 생성 된 후src폴더와 Cargo.toml 파일이이 디렉토리에 있습니다. 소스 코드는 src 폴더 에 있어야 합니다 . src 폴더에 lib.rs 및 movies.rs 파일을 만듭니다. Cargo.toml의 파일 등의 버전 번호, 작성자 이름, 같은 프로젝트의 메타 데이터가 포함됩니다

프로젝트 디렉토리 구조는 다음과 같습니다.

movie-app
   movie-lib/
      -->Cargo.toml
      -->src/
         lib.rs
         movies.rs

2 단계-Cargo.toml 파일을 편집하여 프로젝트 메타 데이터 추가

[package]
name = "movies_lib"
version = "0.1.0"
authors = ["Mohtashim"]

3 단계-lib.rs 파일을 편집합니다.

이 파일에 다음 모듈 정의를 추가하십시오.

pub mod movies;

위의 줄은 공개 모듈을 생성합니다- movies.

4 단계-movies.rs 파일 편집

이 파일은 영화 모듈의 모든 기능을 정의합니다.

pub fn play(name:String){
   println!("Playing movie {} :movies-app",name);
}

위의 코드는 함수를 정의합니다. play() 매개 변수를 받아 콘솔에 출력합니다.

5 단계-라이브러리 상자 만들기

다음을 사용하여 앱 빌드 cargo build명령을 사용하여 라이브러리 상자가 올바르게 구성되었는지 확인합니다. 프로젝트의 루트 인 movie-app 폴더에 있는지 확인하십시오. 빌드가 성공하면 다음 메시지가 터미널에 표시됩니다.

D:\Rust\movie-lib> cargo build
   Compiling movies_lib v0.1.0 (file:///D:/Rust/movie-lib)
   Finished dev [unoptimized + debuginfo] target(s) in 0.67s

6 단계-테스트 애플리케이션 만들기

다른 폴더 생성 movie-lib-testmovie-app 폴더에 Cargo.toml 파일과 src 폴더가 있습니다. 이 프로젝트는 이전에 생성 된 라이브러리 크레이트를 소비하는 바이너리 크레이트이므로 주요 방법이 있어야합니다. src 폴더에 main.rs 파일을 만듭니다. 폴더 구조는 다음과 같습니다.

movie-app
   movie-lib 
   // already completed

   movie-lib-test/
      -->Cargo.toml
      -->src/
         main.rs

7 단계-Cargo.toml 파일에 다음을 추가합니다.

[package]
name = "test_for_movie_lib"
version = "0.1.0"
authors = ["Mohtashim"]

[dependencies]
movies_lib = { path = "../movie-lib" }

NOTE− 라이브러리 폴더의 경로는 종속성으로 설정됩니다. 다음 다이어그램은 두 프로젝트의 내용을 보여줍니다.

8 단계-main.rs 파일에 다음을 추가합니다.

extern crate movies_lib;
use movies_lib::movies::play;
fn main() {
   println!("inside main of test ");
   play("Tutorialspoint".to_string())
}

위 코드는 movies_lib라는 외부 패키지를 가져옵니다. 현재 프로젝트의 Cargo.toml을 확인하여 상자 이름을 확인하십시오.

9 단계-화물 제작 및화물 운송 사용

화물 빌드 및화물 실행을 사용하여 바이너리 프로젝트를 빌드하고 아래와 같이 실행합니다.

Rust의 표준 컬렉션 라이브러리는 가장 일반적인 범용 프로그래밍 데이터 구조를 효율적으로 구현합니다. 이 장에서는 일반적으로 사용되는 컬렉션 인 Vector, HashMap 및 HashSet의 구현에 대해 설명합니다.

벡터

Vector는 크기 조정이 가능한 배열입니다. 인접한 메모리 블록에 값을 저장합니다. 미리 정의 된 구조 Vec를 사용하여 벡터를 만들 수 있습니다. 벡터의 몇 가지 중요한 기능은 다음과 같습니다.

  • 벡터는 런타임에 늘어나거나 줄어들 수 있습니다.

  • Vector는 동종 컬렉션입니다.

  • Vector는 데이터를 특정 순서의 요소 시퀀스로 저장합니다. Vector의 모든 요소에는 고유 한 인덱스 번호가 할당됩니다. 인덱스는 0에서 시작하여 n-1까지 올라갑니다. 여기서 n은 컬렉션의 크기입니다. 예를 들어, 5 개의 요소 모음에서 첫 번째 요소는 인덱스 0에 있고 마지막 요소는 인덱스 4에 있습니다.

  • Vector는 끝에 값을 추가합니다. 즉, 벡터를 사용하여 스택을 구현할 수 있습니다.

  • 벡터에 대한 메모리는 힙에 할당됩니다.

구문-벡터 생성

let mut instance_name = Vec::new();

정적 메소드 새로운 ()VEC의 구조는 벡터 인스턴스를 생성하기 위해 사용된다.

또는 vec!를 사용하여 벡터를 만들 수도 있습니다. 매크로. 구문은 다음과 같습니다.

let vector_name = vec![val1,val2,val3]

다음 표는 Vec 구조에서 일반적으로 사용되는 몇 가지 기능을 나열합니다.

Sr. 아니요 방법 서명 및 설명
1 새로운()

pub fn new()->Vect

비어있는 새 Vec를 생성합니다. 벡터는 요소가 푸시 될 때까지 할당되지 않습니다.

2 푸시()

pub fn push(&mut self, value: T)

컬렉션 뒤에 요소를 추가합니다.

없애다()

pub fn remove(&mut self, index: usize) -> T

벡터 내 위치 인덱스에있는 요소를 제거하고 반환하여 그 뒤의 모든 요소를 ​​왼쪽으로 이동합니다.

4 contains ()

pub fn contains(&self, x: &T) -> bool

슬라이스에 주어진 값을 가진 요소가 포함되어 있으면 true를 반환합니다.

5 len ()

pub fn len(&self) -> usize

'길이'라고도하는 벡터의 요소 수를 반환합니다.

그림 : 벡터 만들기-new ()

벡터를 만들려면, 우리는 정적 메서드를 사용하여 -

fn main() {
   let mut v = Vec::new();
   v.push(20);
   v.push(30);
   v.push(40);

   println!("size of vector is :{}",v.len());
   println!("{:?}",v);
}

위의 예제 는 Vec 구조체에 정의 된 정적 메서드 new () 를 사용하여 Vector를 만듭니다 . 푸시 (발) 함수는 컬렉션 매개 변수로 전달 된 값을 추가한다. len () 함수는 벡터의 길이를 반환합니다.

산출

size of vector is :3
[20, 30, 40]

그림 : 벡터 만들기-vec! 매크로

다음 코드는 vec! 매크로. 벡터의 데이터 유형은 벡터에 할당 된 첫 번째 값으로 유추됩니다.

fn main() {
   let v = vec![1,2,3];
   println!("{:?}",v);
}

산출

[1, 2, 3]

앞서 언급했듯이 벡터는 동일한 데이터 유형의 값만 포함 할 수 있습니다. 다음 스 니펫은 오류 [E0308] : 유형 불일치 오류를 발생시킵니다.

fn main() {
   let v = vec![1,2,3,"hello"];
   println!("{:?}",v);
}

그림 : push ()

컬렉션 끝에 요소를 추가합니다.

fn main() {
   let mut v = Vec::new();
   v.push(20);
   v.push(30);
   v.push(40);
   
   println!("{:?}",v);
}

산출

[20, 30, 40]

그림 : remove ()

벡터 내 위치 인덱스에있는 요소를 제거하고 반환하여 그 뒤의 모든 요소를 ​​왼쪽으로 이동합니다.

fn main() {
   let mut v = vec![10,20,30];
   v.remove(1);
   println!("{:?}",v);
}

산출

[10, 30]

일러스트-contains ()

슬라이스에 주어진 값을 가진 요소가 포함되어 있으면 true를 반환합니다.

fn main() {
   let v = vec![10,20,30];
   if v.contains(&10) {
      println!("found 10");
   }
   println!("{:?}",v);
}

산출

found 10
[10, 20, 30]

그림 : len ()

'길이'라고도하는 벡터의 요소 수를 반환합니다.

fn main() {
   let v = vec![1,2,3];
   println!("size of vector is :{}",v.len());
}

산출

size of vector is :3

벡터에서 값 액세스

벡터의 개별 요소는 해당 인덱스 번호를 사용하여 액세스 할 수 있습니다. 다음 예제는 벡터 광고를 만들고 첫 번째 요소의 값을 인쇄합니다.

fn main() {
   let mut v = Vec::new();
   v.push(20);
   v.push(30);

   println!("{:?}",v[0]);
}
Output: `20`

컬렉션에 대한 참조를 사용하여 벡터의 값을 가져올 수도 있습니다.

fn main() {
   let mut v = Vec::new();
   v.push(20);
   v.push(30);
   v.push(40);
   v.push(500);

   for i in &v {
      println!("{}",i);
   }
   println!("{:?}",v);
}

산출

20
30
40
500
[20, 30, 40, 500]

HashMap

맵은 키-값 쌍 (항목이라고 함)의 모음입니다. 맵의 두 항목은 동일한 키를 가질 수 없습니다. 간단히 말해 맵은 조회 테이블입니다. HashMap은 키와 값을 해시 테이블에 저장합니다. 항목은 임의의 순서로 저장됩니다. 키는 HashMap에서 값을 검색하는 데 사용됩니다. HashMap 구조는std::collections기준 치수. HashMap 구조에 액세스하려면이 모듈을 명시 적으로 가져와야합니다.

구문 : HashMap 생성

let mut instance_name = HashMap::new();

정적 메소드 새로운 ()HashMap의 구조는 HashMap 객체를 생성하는 데 사용된다. 이 메서드는 빈 HashMap을 만듭니다.

일반적으로 사용되는 HashMap 기능은 아래에서 설명합니다.

Sr. 아니요 방법 서명 및 설명
1 끼워 넣다()

pub fn insert(&mut self, k: K, v: V) -> Option

키 / 값 쌍을 삽입합니다. 키가 없으면 None이 반환됩니다. 업데이트 후 이전 값이 반환됩니다.

2 len ()

pub fn len(&self) -> usize

지도의 요소 수를 반환합니다.

가져 오기()

pub fn get<Q: ?Sized>(&lself, k: &Q) -> Option<&V> where K:Borrow Q:Hash+ Eq

키에 해당하는 값에 대한 참조를 반환합니다.

4 iter ()

pub fn iter(&self) -> Iter<K, V>

임의의 순서로 모든 키-값 쌍을 방문하는 반복기입니다. 반복기 요소 유형은 (& 'a K, &'a V)입니다.

5 contains_key

pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool

맵에 지정된 키의 값이 포함되어 있으면 true를 반환합니다.

6 없애다()

pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>

맵에서 키를 제거하고 키가 이전에 맵에있는 경우 저장된 키와 값을 반환합니다.

그림 : insert ()

HashMap에 키 / 값 쌍을 삽입합니다.

use std::collections::HashMap;
fn main(){
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");
   println!("{:?}",stateCodes);
}

위의 프로그램은 HashMap을 만들고 2 개의 키-값 쌍으로 초기화합니다.

산출

{"KL": "Kerala", "MH": "Maharashtra"}

그림 : len ()

지도의 요소 수를 반환합니다.

use std::collections::HashMap;
fn main() {
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");
   println!("size of map is {}",stateCodes.len());
}

위의 예제는 HashMap을 만들고 그 안에있는 총 요소 수를 인쇄합니다.

산출

size of map is 2

일러스트-get ()

키에 해당하는 값에 대한 참조를 반환합니다. 다음 예제 는 HashMap에서 키 KL 의 값을 검색합니다 .

use std::collections::HashMap;
fn main() {
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");
   println!("size of map is {}",stateCodes.len());
   println!("{:?}",stateCodes);

   match stateCodes.get(&"KL") {
      Some(value)=> {
         println!("Value for key KL is {}",value);
      }
      None => {
         println!("nothing found");
      }
   }
}

산출

size of map is 2
{"KL": "Kerala", "MH": "Maharashtra"}
Value for key KL is Kerala

삽화-iter ()

모든 키-값 쌍에 대한 참조를 임의의 순서로 포함하는 반복기를 반환합니다.

use std::collections::HashMap;
fn main() {
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");

   for (key, val) in stateCodes.iter() {
      println!("key: {} val: {}", key, val);
   }
}

산출

key: MH val: Maharashtra
key: KL val: Kerala

그림 : contains_key ()

맵에 지정된 키의 값이 포함되어 있으면 true를 반환합니다.

use std::collections::HashMap;
fn main() {
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");
   stateCodes.insert("GJ","Gujarat");

   if stateCodes.contains_key(&"GJ") {
      println!("found key");
   }
}

산출

found key

그림 : remove ()

지도에서 키를 제거합니다.

use std::collections::HashMap;
fn main() {
   let mut stateCodes = HashMap::new();
   stateCodes.insert("KL","Kerala");
   stateCodes.insert("MH","Maharashtra");
   stateCodes.insert("GJ","Gujarat");

   println!("length of the hashmap {}",stateCodes.len());
   stateCodes.remove(&"GJ");
   println!("length of the hashmap after remove() {}",stateCodes.len());
}

산출

length of the hashmap 3
length of the hashmap after remove() 2

HashSet

HashSet은 T 유형의 고유 한 값 집합입니다. 값을 추가하고 제거하는 것은 빠르며 주어진 값이 집합에 있는지 여부를 묻는 것도 빠릅니다. HashSet 구조는 std :: collections 모듈에 정의되어 있습니다. HashSet 구조에 액세스하려면이 모듈을 명시 적으로 가져와야합니다.

구문 : HashSet 생성

let mut hash_set_name = HashSet::new();

HashSet 구조 의 정적 메서드 new 는 HashSet을 만드는 데 사용됩니다. 이 메서드는 빈 HashSet을 만듭니다.

다음 표에는 HashSet 구조에서 일반적으로 사용되는 몇 가지 메서드가 나열되어 있습니다.

Sr. 아니요 방법 서명 및 설명
1 끼워 넣다()

pub fn insert(&mut self, value: T) -> bool

세트에 값을 추가합니다. 집합에이 값이 없으면 true가 반환되고 그렇지 않으면 false가 반환됩니다.

2 len ()

pub fn len(&self) -> usize

집합의 요소 수를 반환합니다.

가져 오기()

pub fn get<Q:?Sized>(&self, value: &Q) -> Option<&T> where T: Borrow,Q: Hash + Eq,

주어진 값과 동일한 경우 집합의 값에 대한 참조를 반환합니다.

4 iter ()

pub fn iter(&self) -> Iter

임의의 순서로 모든 요소를 ​​방문하는 반복기를 반환합니다. 반복기 요소 유형은 & 'a T입니다.

5 contains_key

pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool

세트에 값이 포함되어 있으면 true를 반환합니다.

6 없애다()

pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool

세트에서 값을 제거합니다. 값이 세트에 있으면 true를 리턴합니다.

스톡 콘텐츠-insert ()

세트에 값을 추가합니다. HashSet은 컬렉션에 중복 값을 추가하지 않습니다.

use std::collections::HashSet;
fn main() {
   let mut names = HashSet::new();

   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");
   names.insert("Mohtashim");//duplicates not added

   println!("{:?}",names);
}

산출

{"TutorialsPoint", "Kannan", "Mohtashim"}

그림 : len ()

집합의 요소 수를 반환합니다.

use std::collections::HashSet;
fn main() {
   let mut names = HashSet::new();
   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");
   println!("size of the set is {}",names.len());
}

산출

size of the set is 3

일러스트-iter ()

모든 요소를 ​​임의의 순서로 방문하는 반복기를 되돌립니다.

use std::collections::HashSet;
fn main() {
   let mut names = HashSet::new();
   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");
   names.insert("Mohtashim");

   for name in names.iter() {
      println!("{}",name);
   }
}

산출

TutorialsPoint
Mohtashim
Kannan

그림 : get ()

세트의 값에 대한 참조를 반환합니다 (있는 경우). 주어진 값과 동일합니다.

use std::collections::HashSet;
fn main() {
   let mut names = HashSet::new();
   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");
   names.insert("Mohtashim");

   match names.get(&"Mohtashim"){
      Some(value)=>{
         println!("found {}",value);
      }
      None =>{
         println!("not found");
      }
   }
   println!("{:?}",names);
}

산출

found Mohtashim
{"Kannan", "Mohtashim", "TutorialsPoint"}

일러스트-contains ()

세트에 값이 포함되어 있으면 true를 반환합니다.

use std::collections::HashSet;

fn main() {
   let mut names = HashSet::new();
   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");

   if names.contains(&"Kannan") {
      println!("found name");
   }  
}

산출

found name

그림 : remove ()

세트에서 값을 제거합니다.

use std::collections::HashSet;

fn main() {
   let mut names = HashSet::new();
   names.insert("Mohtashim");
   names.insert("Kannan");
   names.insert("TutorialsPoint");
   println!("length of the Hashset: {}",names.len());
   names.remove(&"Kannan");
   println!("length of the Hashset after remove() : {}",names.len());
}

산출

length of the Hashset: 3
length of the Hashset after remove() : 2

Rust에서 오류는 아래 표와 같이 두 가지 주요 범주로 분류 될 수 있습니다.

Sr. 아니요 이름 및 설명 용법
1

Recoverable

처리 할 수있는 오류

결과 열거
2

UnRecoverable

처리 할 수없는 오류

패닉 매크로

복구 가능한 오류는 수정할 수있는 오류입니다. 프로그램은 실패한 작업을 재 시도하거나 복구 가능한 오류가 발생한 경우 대체 작업 과정을 지정할 수 있습니다. 복구 가능한 오류로 인해 프로그램이 갑자기 실패하는 것은 아닙니다. 복구 가능한 오류의 예는 파일을 찾을 수 없음 오류입니다.

복구 할 수없는 오류로 인해 프로그램이 갑자기 실패합니다. 복구 할 수없는 오류가 발생하면 프로그램을 정상 상태로 되돌릴 수 없습니다. 실패한 작업을 다시 시도하거나 오류를 취소 할 수 없습니다. 복구 할 수없는 오류의 예는 어레이 끝을 벗어난 위치에 액세스하려는 것입니다.

다른 프로그래밍 언어와 달리 Rust에는 예외가 없습니다. 복구 가능한 오류에 대해 enum Result <T, E> 를 반환 하고panic프로그램에서 복구 할 수없는 오류가 발생한 경우 매크로. 공황 매크로 갑자기 종료 프로그램을 발생합니다.

패닉 매크로 및 복구 할 수없는 오류

공황! 매크로를 사용하면 프로그램이 즉시 종료되고 프로그램 호출자에게 피드백을 제공 할 수 있습니다. 프로그램이 복구 불가능한 상태에 도달 할 때 사용해야합니다.

fn main() {
   panic!("Hello");
   println!("End of main"); //unreachable statement
}

위의 예에서 프로그램은 패닉 이 발생하면 즉시 종료됩니다 ! 매크로.

산출

thread 'main' panicked at 'Hello', main.rs:3

그림 : 패닉! 매크로

fn main() {
   let a = [10,20,30];
   a[10]; //invokes a panic since index 10 cannot be reached
}

출력은 다음과 같습니다.

warning: this expression will panic at run-time
--> main.rs:4:4
  |
4 | a[10];
  | ^^^^^ index out of bounds: the len is 3 but the index is 10

$main
thread 'main' panicked at 'index out of bounds: the len 
is 3 but the index is 10', main.rs:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

프로그램이 패닉을 일으킬 수 있습니다! 아래 예제와 같이 비즈니스 규칙이 위반 된 경우 매크로-

fn main() {
   let no = 13; 
   //try with odd and even
   if no%2 == 0 {
      println!("Thank you , number is even");
   } else {
      panic!("NOT_AN_EVEN"); 
   }
   println!("End of main");
}

위의 예는 변수에 할당 된 값이 홀수이면 오류를 반환합니다.

산출

thread 'main' panicked at 'NOT_AN_EVEN', main.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

결과 열거 및 복구 가능한 오류

Enum Result – <T, E>를 사용하여 복구 가능한 오류를 처리 할 수 ​​있습니다. 두 가지 변형이 있습니다.OKErr. TE 일반 유형 매개 변수입니다. T OK 변형 내에서 성공한 경우 반환 될 값의 유형을 나타냅니다. E Err 변형 내의 실패 사례에서 반환 될 오류 유형을 나타냅니다.

enum Result<T,E> {
   OK(T),
   Err(E)
}

예를 들어 이것을 이해합시다.

use std::fs::File;
fn main() {
   let f = File::open("main.jpg"); 
   //this file does not exist
   println!("{:?}",f);
}

프로그램은 파일이 이미 존재하면 OK (파일)를 반환 하고 파일이 없으면 Err (Error)를 반환합니다.

Err(Error { repr: Os { code: 2, message: "No such file or directory" } })

이제 Err 변형을 처리하는 방법을 살펴 보겠습니다.

다음 예제는 다음을 사용하여 파일을 여는 동안 반환 된 오류를 처리합니다. match 성명서

use std::fs::File;
fn main() {
   let f = File::open("main.jpg");   // main.jpg doesn't exist
   match f {
      Ok(f)=> {
         println!("file found {:?}",f);
      },
      Err(e)=> {
         println!("file not found \n{:?}",e);   //handled error
      }
   }
   println!("end of main");
}

NOTE− 프로그램은 파일을 찾을 수 없더라도 메인 이벤트의 을 인쇄합니다 . 이것은 프로그램이 오류를 정상적으로 처리했음을 의미합니다.

산출

file not found
Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
end of main

삽화

is_even 수가 짝수가 아닌 경우 함수는 오류를 반환합니다. main () 함수는이 오류를 처리합니다.

fn main(){
   let result = is_even(13);
   match result {
      Ok(d)=>{
         println!("no is even {}",d);
      },
      Err(msg)=>{
         println!("Error msg is {}",msg);
      }
   }
   println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
   if no%2==0 {
      return Ok(true);
   } else {
      return Err("NOT_AN_EVEN".to_string());
   }
}

NOTE- 주요 기능 핸들이 정상적으로 오류 때문에 종료주요 문은 인쇄됩니다.

산출

Error msg is NOT_AN_EVEN
end of main

unwrap () 및 expect ()

표준 라이브러리에는 enum-Result <T, E> 및 Option <T> 모두 구현 하는 몇 가지 도우미 메서드가 포함되어 있습니다 . 실제로 실패 할 것으로 예상하지 않는 오류 사례를 단순화하는 데 사용할 수 있습니다. 메서드에서 성공한 경우 "unwrap"함수를 사용하여 실제 결과를 추출합니다.

Sr. 아니요 방법 서명 및 설명
1 풀다

unwrap(self): T

self가 Ok / Some 일 것으로 예상하고 그 안에 포함 된 값을 반환합니다. 만약 그렇다면Err 또는 None 대신 오류 내용이 표시되면서 패닉이 발생합니다.

2 배고 있다

expect(self, msg: &str): T

오류 내용에 추가로 당황하기 전에 사용자 정의 메시지를 출력한다는 점을 제외하면 unwrap과 유사합니다.

풀다()

unwrap () 함수는 작업이 성공한 실제 결과를 반환합니다. 작업이 실패하면 기본 오류 메시지와 함께 패닉을 반환합니다. 이 함수는 match 문의 약자입니다. 이것은 아래 예에 나와 있습니다.

fn main(){
   let result = is_even(10).unwrap();
   println!("result is {}",result);
   println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
   if no%2==0 {
      return Ok(true);
   } else {
      return Err("NOT_AN_EVEN".to_string());
   }
}
result is true
end of main

위의 코드를 수정하여 홀수를 is_even() 함수.

포장을 벗긴 () 함수는 당황 아래와 같이 기본 오류 메시지를 반환합니다

thread 'main' panicked at 'called `Result::unwrap()` on 
an `Err` value: "NOT_AN_EVEN"', libcore\result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace

배고 있다()

프로그램은 패닉이 발생한 경우 사용자 지정 오류 메시지를 반환 할 수 있습니다. 이것은 다음 예에 나와 있습니다.

use std::fs::File;
fn main(){
   let f = File::open("pqr.txt").expect("File not able to open");
   //file does not exist
   println!("end of main");
}

expect () 함수는 unwrap ()과 유사합니다. 유일한 차이점은 expect을 사용하여 사용자 지정 오류 메시지를 표시 할 수 있다는 것입니다.

산출

thread 'main' panicked at 'File not able to open: Error { repr: Os 
{ code: 2, message: "No such file or directory" } }', src/libcore/result.rs:860
note: Run with `RUST_BACKTRACE=1` for a backtrace.

제네릭은 유형이 다른 여러 컨텍스트에 대한 코드를 작성하는 기능입니다. Rust에서 제네릭은 데이터 유형과 특성의 매개 변수화를 나타냅니다. Generics를 사용하면 코드 중복을 줄이고 형식 안전성을 제공하여보다 간결하고 깔끔한 코드를 작성할 수 있습니다. Generics의 개념은 메서드, 함수, 구조, 열거 형, 컬렉션 및 특성에 적용될 수 있습니다.

그만큼 <T> syntax유형 매개 변수라고하는이 매개 변수는 제네릭 구문을 선언하는 데 사용됩니다. T 는 모든 데이터 유형을 나타냅니다.

그림 : 일반 컬렉션

다음 예제에서는 정수만 저장할 수있는 벡터를 선언합니다.

fn main(){
   let mut vector_integer: Vec<i32> = vec![20,30];
   vector_integer.push(40);
   println!("{:?}",vector_integer);
}

산출

[20, 30, 40]

다음 스 니펫을 고려하십시오-

fn main() {
   let mut vector_integer: Vec<i32> = vec![20,30];
   vector_integer.push(40);
   vector_integer.push("hello"); 
   //error[E0308]: mismatched types
   println!("{:?}",vector_integer);
}

위의 예는 정수 유형의 벡터가 정수 값만 저장할 수 있음을 보여줍니다. 따라서 문자열 값을 컬렉션에 푸시하려고하면 컴파일러가 오류를 반환합니다. 제네릭은 컬렉션의 형식을보다 안전하게 만듭니다.

그림 : 일반 구조

유형 매개 변수는 컴파일러가 나중에 채울 유형을 나타냅니다.

struct Data<T> {
   value:T,
}
fn main() {
   //generic type of i32
   let t:Data<i32> = Data{value:350};
   println!("value is :{} ",t.value);
   //generic type of String
   let t2:Data<String> = Data{value:"Tom".to_string()};
   println!("value is :{} ",t2.value);
}

위의 예제는 Data 라는 일반 구조를 선언합니다 . <T> 유형은 어떤 유형의 데이터를 나타낸다. 주 () 구조체의 정수 인스턴스와 문자열 인스턴스 - 함수는 두 개의 인스턴스를 생성한다.

산출

value is :350
value is :Tom

특성

특성은 여러 구조에서 표준 동작 (방법) 집합을 구현하는 데 사용할 수 있습니다. 특성은 다음과 같습니다.interfaces객체 지향 프로그래밍에서. 특성의 구문은 다음과 같습니다.

특성 선언

trait some_trait {
   //abstract or method which is empty
   fn method1(&self);
   // this is already implemented , this is free
   fn method2(&self){
      //some contents of method2
   }
}

특성에는 구체적인 방법 (본문이있는 방법) 또는 추상적 인 방법 (본문이없는 방법)이 포함될 수 있습니다. Trait을 구현하는 모든 구조가 메서드 정의를 공유 할 경우 구체적인 메서드를 사용합니다. 그러나 구조는 특성에 의해 정의 된 함수를 재정의하도록 선택할 수 있습니다.

구현 구조에 따라 메서드 정의가 다른 경우 추상 메서드를 사용합니다.

구문-특성 구현

impl some_trait for structure_name {
   // implement method1() there..
   fn method1(&self ){
   }
}

다음 예제는 구조 책에 의해 구현되는 print () 메서드를 사용하여 Printable 특성을 정의합니다 .

fn main(){
   //create an instance of the structure
   let b1 = Book {
      id:1001,
      name:"Rust in Action"
   };
   b1.print();
}
//declare a structure
struct Book {
   name:&'static str,
   id:u32
}
//declare a trait
trait Printable {
   fn print(&self);
}
//implement the trait
impl Printable for Book {
   fn print(&self){
      println!("Printing book with id:{} and name {}",self.id,self.name)
   }
}

산출

Printing book with id:1001 and name Rust in Action

일반 기능

이 예제는 전달 된 매개 변수를 표시하는 일반 함수를 정의합니다. 매개 변수는 모든 유형이 될 수 있습니다. 매개 변수의 유형은 그 값이 println!에 의해 인쇄 될 수 있도록 Display 특성을 구현해야합니다. 매크로.

use std::fmt::Display;

fn main(){
   print_pro(10 as u8);
   print_pro(20 as u16);
   print_pro("Hello TutorialsPoint");
}

fn print_pro<T:Display>(t:T){
   println!("Inside print_pro generic function:");
   println!("{}",t);
}

산출

Inside print_pro generic function:
10
Inside print_pro generic function:
20
Inside print_pro generic function:
Hello TutorialsPoint

이 장에서는 표준 입력 (키보드)에서 값을 받아들이고 표준 출력 (콘솔)에 값을 표시하는 방법에 대해 설명합니다. 이 장에서는 명령 줄 인수 전달에 대해서도 설명합니다.

리더 및 라이터 유형

입력과 출력을위한 Rust의 표준 라이브러리 기능은 두 가지 특성을 중심으로 구성됩니다.

  • Read
  • Write
Sr. 아니요 특성 및 설명
1

Read

Read를 구현하는 유형에는 바이트 지향 입력을위한 메소드가 있습니다. 그들은 독자라고

Stdin, 파일
2

Write

쓰기를 구현하는 유형은 바이트 지향 및 UTF-8 텍스트 출력을 모두 지원합니다. 그들은 작가라고 불립니다.

Stdout, 파일

특성 읽기

Readers프로그램이 바이트를 읽을 수있는 구성 요소입니다. 예를 들어 키보드, 파일 등에서 입력 읽기가 있습니다.read_line() 이 특성의 메서드는 파일 또는 표준 입력 스트림에서 한 번에 한 줄씩 데이터를 읽는 데 사용할 수 있습니다.

Sr. 아니요 특성 방법 및 설명
1 읽다

read_line(&mut line)->Result

한 줄의 텍스트를 읽고 문자열 인 줄에 추가합니다. 반환 값은 읽은 바이트 수인 io :: Result입니다.

그림-콘솔에서 읽기-stdin ()

Rust 프로그램은 런타임에 사용자로부터 값을 받아야 할 수도 있습니다. 다음 예제는 표준 입력 (키보드)에서 값을 읽고 콘솔에 인쇄합니다.

fn main(){
   let mut line = String::new();
   println!("Enter your name :");
   let b1 = std::io::stdin().read_line(&mut line).unwrap();
   println!("Hello , {}", line);
   println!("no of bytes read , {}", b1);
}

표준 입력 () 함수는 어떤 현재 프로세스의 표준 입력 스트림 핸들 리턴 read_line의 기능이 적용될 수있다. 이 함수는 줄 끝 문자를 만날 때 입력 버퍼에있는 모든 문자를 읽으려고합니다.

산출

Enter your name :
Mohtashim
Hello , Mohtashim
no of bytes read , 10

특성 쓰기

Writers프로그램이 바이트를 쓸 수있는 구성 요소입니다. 예를 들면 콘솔에 값 인쇄, 파일에 쓰기 등이 있습니다.이 특성의 write () 메서드는 파일 또는 표준 출력 스트림에 데이터를 쓰는 데 사용할 수 있습니다.

Sr. 아니요 특성 방법 및 설명
1 쓰다

write(&buf)->Result

슬라이스 buf의 일부 바이트를 기본 스트림에 씁니다. 기록 된 바이트 수인 io :: Result를 반환합니다.

그림-콘솔에 쓰기-stdout ()

인쇄! 또는 println! 매크로를 사용하여 콘솔에 텍스트를 표시 할 수 있습니다. 그러나 write () 표준 라이브러리 함수를 사용하여 일부 텍스트를 표준 출력에 표시 할 수도 있습니다 .

이것을 이해하기위한 예를 고려해 보겠습니다.

use std::io::Write;
fn main() {
   let b1 = std::io::stdout().write("Tutorials ".as_bytes()).unwrap();
   let b2 = std::io::stdout().write(String::from("Point").as_bytes()).unwrap();
   std::io::stdout().write(format!("\nbytes written {}",(b1+b2)).as_bytes()).unwrap();
}

산출

Tutorials Point
bytes written 15

표준 출력 () 표준 라이브러리 함수는, 현재의 프로세스의 표준 출력 스트림에 핸들을 리턴되는 행write기능을 적용 할 수 있습니다. write () 메서드는 enum, Result를 반환합니다. unwrap ()은 열거에서 실제 결과를 추출하는 도우미 메서드입니다. unwrap 메서드는 오류가 발생하면 패닉을 보냅니다.

NOTE − 파일 IO는 다음 장에서 설명합니다.

명령 줄 인수

명령 줄 인수는 프로그램을 실행하기 전에 프로그램에 전달됩니다. 함수에 전달되는 매개 변수와 같습니다. CommandLine 매개 변수를 사용하여 값을 main () 함수 에 전달할 수 있습니다 . 그만큼std::env::args() 명령 줄 인수를 반환합니다.

삽화

다음 예제에서는 값을 main () 함수에 명령 줄 인수로 전달합니다. 프로그램은 main.rs 파일 이름으로 작성 됩니다.

//main.rs
fn main(){
   let cmd_line = std::env::args();
   println!("No of elements in arguments is :{}",cmd_line.len()); 
   //print total number of values passed
   for arg in cmd_line {
      println!("[{}]",arg); //print all values passed 
      as commandline arguments
   }
}

프로그램은 일단 컴파일되면 main.exe 파일을 생성합니다 . 여러 명령 줄 매개 변수는 공백으로 구분해야합니다. 터미널에서 main.exemain.exe hello tutorialspoint 로 실행합니다 .

NOTEhellotutorialspoint 는 명령 줄 인수입니다.

산출

No of elements in arguments is :3
[main.exe]
[hello]
[tutorialspoint]

출력에는 main.exe 가 첫 번째 인수이므로 3 개의 인수가 표시됩니다 .

삽화

다음 프로그램은 명령 줄 인수로 전달 된 값의 합계를 계산합니다. 공백으로 구분 된 목록 정수 값이 프로그램에 전달됩니다.

fn main(){
   let cmd_line = std::env::args();
   println!("No of elements in arguments is 
   :{}",cmd_line.len()); 
   // total number of elements passed

   let mut sum = 0;
   let mut has_read_first_arg = false;

   //iterate through all the arguments and calculate their sum

   for arg in cmd_line {
      if has_read_first_arg { //skip the first argument since it is the exe file name
         sum += arg.parse::<i32>().unwrap();
      }
      has_read_first_arg = true; 
      // set the flag to true to calculate sum for the subsequent arguments.
   }
   println!("sum is {}",sum);
}

프로그램을 main.exe 1 2 3 4로 실행하면 출력은 다음과 같습니다.

No of elements in arguments is :5
sum is 10

콘솔에 읽고 쓰는 것 외에도 Rust는 파일을 읽고 쓸 수 있습니다.

File 구조체는 파일을 나타냅니다. 프로그램이 파일에 대해 읽기-쓰기 작업을 수행 할 수 있도록합니다. File 구조체의 모든 메서드는 io :: Result 열거 형의 변형을 반환합니다.

일반적으로 사용되는 File 구조체의 방법은 아래 표에 나열되어 있습니다.

Sr. 아니요 기준 치수 방법 서명 기술
1 std :: fs :: 파일 열다() pub fn open <P : AsRef> (경로 : P)-> 결과 open static 메서드를 사용하여 읽기 전용 모드로 파일을 열 수 있습니다.
2 std :: fs :: 파일 창조하다() pub fn create <P : AsRef> (경로 : P)-> 결과 정적 메서드는 쓰기 전용 모드로 파일을 엽니 다. 파일이 이미 존재하는 경우 이전 콘텐츠가 삭제됩니다. 그렇지 않으면 새 파일이 생성됩니다.
std :: fs :: remove_file 파일을 지우다() pub fn remove_file <P : AsRef> (경로 : P)-> 결과 <()> 파일 시스템에서 파일을 제거합니다. 파일이 즉시 삭제된다는 보장은 없습니다.
4 std :: fs :: OpenOptions append () pub fn append (& mut self, append : bool)-> & mut OpenOptions 파일의 추가 모드에 대한 옵션을 설정합니다.
5 std :: io :: 쓰기 write_all () fn write_all (& mut self, buf : & [u8])-> 결과 <()> 이 쓰기에 전체 버퍼 쓰기를 시도합니다.
6 std :: io :: 읽기 read_to_string () fn read_to_string (& mut self, buf : & mut String)-> 결과 이 소스에서 EOF까지 모든 바이트를 읽고 buf에 추가합니다.

파일에 쓰기

파일 작성 방법을 이해하는 예를 살펴 보겠습니다.

다음 프로그램은 'data.txt'파일을 생성합니다. create () 메서드는 파일을 만드는 데 사용됩니다. 이 메서드는 파일이 성공적으로 생성 된 경우 파일 핸들을 반환합니다. 마지막 줄 write_all 함수는 새로 생성 된 파일에 바이트를 기록합니다. 작업 중 하나라도 실패하면 expect () 함수는 오류 메시지를 반환합니다.

use std::io::Write;
fn main() {
   let mut file = std::fs::File::create("data.txt").expect("create failed");
   file.write_all("Hello World".as_bytes()).expect("write failed");
   file.write_all("\nTutorialsPoint".as_bytes()).expect("write failed");
   println!("data written to file" );
}

산출

data written to file

파일에서 읽기

다음 프로그램은 data.txt 파일의 내용을 읽고 콘솔에 인쇄합니다. "열기"기능은 기존 파일을 여는 데 사용됩니다. 파일의 절대 또는 상대 경로는 매개 변수로 open () 함수에 전달됩니다. open () 함수는 파일이 존재하지 않거나 어떤 이유로 든 액세스 할 수없는 경우 예외를 발생시킵니다. 성공하면 해당 파일에 대한 파일 핸들이 "file"변수에 할당됩니다.

"file"핸들의 "read_to_string"함수는 해당 파일의 내용을 문자열 변수로 읽는 데 사용됩니다.

use std::io::Read;

fn main(){
   let mut file = std::fs::File::open("data.txt").unwrap();
   let mut contents = String::new();
   file.read_to_string(&mut contents).unwrap();
   print!("{}", contents);
}

산출

Hello World
TutorialsPoint

파일 삭제

다음 예제에서는 remove_file () 함수를 사용하여 파일을 삭제합니다. expect () 함수는 오류가 발생하는 경우 사용자 지정 메시지를 반환합니다.

use std::fs;
fn main() {
   fs::remove_file("data.txt").expect("could not remove file");
   println!("file is removed");
}

산출

file is removed

파일에 데이터 추가

append () 함수는 파일 끝에 데이터를 씁니다. 이것은 아래 주어진 예에 나와 있습니다.

use std::fs::OpenOptions;
use std::io::Write;

fn main() {
   let mut file = OpenOptions::new().append(true).open("data.txt").expect(
      "cannot open file");
   file.write_all("Hello World".as_bytes()).expect("write failed");
   file.write_all("\nTutorialsPoint".as_bytes()).expect("write failed");
   println!("file append success");
}

산출

file append success

파일 복사

다음 예제는 파일의 내용을 새 파일로 복사합니다.

use std::io::Read;
use std::io::Write;

fn main() {
   let mut command_line: std::env::Args = std::env::args();
   command_line.next().unwrap();
   // skip the executable file name
   // accept the source file
   let source = command_line.next().unwrap();
   // accept the destination file
   let destination = command_line.next().unwrap();
   let mut file_in = std::fs::File::open(source).unwrap();
   let mut file_out = std::fs::File::create(destination).unwrap();
   let mut buffer = [0u8; 4096];
   loop {
      let nbytes = file_in.read(&mut buffer).unwrap();
      file_out.write(&buffer[..nbytes]).unwrap();
      if nbytes < buffer.len() { break; }
   }
}

위의 프로그램을 main.exe data.txt datacopy.txt 로 실행합니다 . 파일을 실행하는 동안 두 개의 명령 줄 인수가 전달됩니다.

  • 소스 파일의 경로
  • 대상 파일

Cargo는 RUST의 패키지 관리자입니다. 이것은 도구처럼 작동하고 Rust 프로젝트를 관리합니다.

일반적으로 사용되는화물 명령은 아래 표에 나열되어 있습니다.

Sr. 아니요 명령 및 설명
1

cargo build

현재 프로젝트를 컴파일합니다.

2

cargo check

현재 프로젝트를 분석하고 오류를보고하지만 개체 파일은 빌드하지 않습니다.

cargo run

src / main.rs를 빌드하고 실행합니다.

4

cargo clean

대상 디렉토리를 제거합니다.

5

cargo update

Cargo.lock에 나열된 종속성을 업데이트합니다.

6

cargo new

새로운화물 프로젝트를 생성합니다.

Cargo는 타사 라이브러리를 다운로드하는 데 도움이됩니다. 따라서 패키지 관리자처럼 작동합니다. 자신 만의 라이브러리를 만들 수도 있습니다. 카고는 Rust를 설치할 때 기본적으로 설치됩니다.

새로운화물 프로젝트를 생성하기 위해 아래에 주어진 명령을 사용할 수 있습니다.

바이너리 상자 만들기

cargo new project_name --bin

도서관 상자 만들기

cargo new project_name --lib

화물의 현재 버전을 확인하려면 다음 명령을 실행하십시오.

cargo --version

일러스트-Binary Cargo 프로젝트 만들기

게임은 임의의 숫자를 생성하고 사용자에게 숫자를 추측하도록합니다.

1 단계-프로젝트 폴더 만들기

터미널을 열고 다음 명령 cargo new guess-game-app --bin을 입력하십시오 .

그러면 다음과 같은 폴더 구조가 생성됩니다.

guess-game-app/
   -->Cargo.toml
   -->src/
      main.rs

화물 새로운 명령은 상자를 만드는 데 사용됩니다. --bin 플래그는 작성되는 상자가 진 상자 있음을 나타냅니다. 공개 상자는 crates.io라는 중앙 저장소에 저장됩니다.https://crates.io/.

2 단계-외부 라이브러리에 대한 참조 포함

이 예제는 난수를 생성해야합니다. 내부 표준 라이브러리는 난수 생성 로직을 제공하지 않기 때문에 외부 라이브러리 나 크레이트를 살펴 봐야합니다. 사용하자randcrates.io 웹 사이트 crates.io 에서 구할 수있는 상자

그만큼 https://crates.io/crates/rand난수 생성을위한 Rust 라이브러리입니다. Rand는 난수를 생성하고, 유용한 유형과 분포로 변환하고, 일부 난수 관련 알고리즘을 생성하는 유틸리티를 제공합니다.

다음 다이어그램은 crate.io 웹 사이트와 rand crate에 대한 검색 결과를 보여줍니다.

rand crate의 버전을 Cargo.toml 파일 rand = "0.5.5"에 복사합니다 .

[package]
name = "guess-game-app"
version = "0.1.0"
authors = ["Mohtashim"]

[dependencies]
rand = "0.5.5"

3 단계 : 프로젝트 컴파일

프로젝트 폴더로 이동합니다. 명령 실행cargo build 터미널 창에서-

Updating registry `https://github.com/rust-lang/crates.io-index`
Downloading rand v0.5.5
Downloading rand_core v0.2.2
Downloading winapi v0.3.6
Downloading rand_core v0.3.0
   Compiling winapi v0.3.6
   Compiling rand_core v0.3.0
   Compiling rand_core v0.2.2
   Compiling rand v0.5.5
   Compiling guess-game-app v0.1.0 
   (file:///E:/RustWorks/RustRepo/Code_Snippets/cargo-projects/guess-game-app)
   Finished dev [unoptimized + debuginfo] target(s) in 1m 07s

랜드 상자와 모든 전이 종속성 (rand의 내부 종속성)은 자동으로 다운로드됩니다.

4 단계-비즈니스 로직 이해

이제 숫자 추측 게임에서 비즈니스 로직이 어떻게 작동하는지 살펴 보겠습니다.

  • 게임은 처음에 난수를 생성합니다.

  • 사용자는 입력을 입력하고 숫자를 추측해야합니다.

  • 숫자가 생성 된 숫자보다 작 으면 "너무 낮음"메시지가 인쇄됩니다.

  • 숫자가 생성 된 숫자보다 크면 "너무 높음"메시지가 인쇄됩니다.

  • 사용자가 프로그램에서 생성 한 번호를 입력하면 게임이 종료됩니다.

5 단계-main.rs 파일 편집

main.rs 파일에 비즈니스 로직을 추가하십시오.

use std::io;
extern crate rand; 
//importing external crate
use rand::random;
fn get_guess() -> u8 {
   loop {
      println!("Input guess") ;
      let mut guess = String::new();
      io::stdin().read_line(&mut guess)
         .expect("could not read from stdin");
      match guess.trim().parse::<u8>(){ //remember to trim input to avoid enter spaces
         Ok(v) => return v,
         Err(e) => println!("could not understand input {}",e)
      }
   }
}
fn handle_guess(guess:u8,correct:u8)-> bool {
   if guess < correct {
      println!("Too low");
      false

   } else if guess> correct {
      println!("Too high");
      false
   } else {
      println!("You go it ..");
      true
   }
}
fn main() {
   println!("Welcome to no guessing game");

   let correct:u8 = random();
   println!("correct value is {}",correct);
   loop {
      let guess = get_guess();
      if handle_guess(guess,correct){
         break;
      }
   }
}

6 단계-프로젝트 컴파일 및 실행

터미널에서 화물 실행 명령을 실행합니다 . 터미널이 프로젝트 디렉토리를 가리키는 지 확인하십시오.

Welcome to no guessing game
correct value is 97
Input guess
20
Too low
Input guess
100
Too high
Input guess
97
You got it ..

이 장에서는 RUST에서 반복기와 클로저가 작동하는 방식을 배웁니다.

반복자

반복자는 배열, 벡터, 맵 등과 같은 값 모음을 반복하는 데 도움이됩니다. 반복기는 Rust 표준 라이브러리에 정의 된 반복기 특성을 구현합니다. ITER () 메서드는 컬렉션의 반복자 객체를 반환합니다. 반복기 객체의 값을 항목이라고합니다. 반복자 의 next () 메서드를 사용하여 항목을 순회 할 수 있습니다. 다음 () 는 컬렉션의 끝에 도달 할 때 방법은 값 없음 반환하지 않는다.

다음 예제에서는 반복기를 사용하여 배열에서 값을 읽습니다.

fn main() {
   //declare an array
   let a = [10,20,30];

   let mut iter = a.iter(); 
   // fetch an iterator object for the array
   println!("{:?}",iter);

   //fetch individual values from the iterator object
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
}

산출

Iter([10, 20, 30])
Some(10)
Some(20)
Some(30)
None

배열 또는 벡터와 같은 컬렉션이 반복자 특성을 구현하는 경우 아래와 같이 for ... in 구문을 사용하여 탐색 할 수 있습니다.

fn main() {
   let a = [10,20,30];
   let iter = a.iter();
   for data in iter{
      print!("{}\t",data);
   }
}

산출

10 20 30

다음 세 가지 메서드는 컬렉션에서 반복기 개체를 반환합니다. 여기서 T는 컬렉션의 요소를 나타냅니다.

Sr. 아니요 방법 및 설명
1

iter()

& T (T에 대한 참조)에 대한 반복자를 제공합니다.

2

into_iter()

T에 대한 반복자를 제공합니다.

iter_mut()

& mut T에 대한 반복자를 제공합니다.

삽화 : iter ()

iter () 함수는 차용 개념을 사용합니다. 컬렉션의 각 요소에 대한 참조를 반환하고 컬렉션은 그대로두고 루프 후에 재사용 할 수 있습니다.

fn main() {
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter() {
      match name {
         &"Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names); 
   // reusing the collection after iteration
}

산출

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

일러스트-into_iter ()

이 기능은 소유권 개념을 사용합니다. 컬렉션의 값을 iter 객체로 이동합니다. 즉, 컬렉션이 소비되고 더 이상 재사용 할 수 없습니다.

fn main(){
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.into_iter() {
      match name {
         "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   // cannot reuse the collection after iteration
   //println!("{:?}",names); 
   //Error:Cannot access after ownership move
}

산출

Hello Kannan
There is a rustacean among us!
Hello Kiran

일러스트-for 및 iter_mut ()

이 함수는 iter () 함수 와 같습니다 . 그러나이 함수는 컬렉션 내의 요소를 수정할 수 있습니다.

fn main() {
   let mut names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter_mut() {
      match name {
         &mut "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names);
   //// reusing the collection after iteration
}

산출

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

폐쇄

클로저는 다른 기능 내의 기능을 나타냅니다. 이름이없는 함수 인 익명 함수입니다. 클로저는 변수에 함수를 할당하는 데 사용할 수 있습니다. 이를 통해 프로그램은 함수를 매개 변수로 다른 함수에 전달할 수 있습니다. 클로저는 인라인 함수라고도합니다. 외부 함수의 변수는 인라인 함수로 액세스 할 수 있습니다.

구문 : 클로저 정의

클로저 정의는 선택적으로 매개 변수를 가질 수 있습니다. 매개 변수는 두 개의 수직 막대로 묶여 있습니다.

let closure_function = |parameter| {
   //logic
}

클로저를 호출하는 구문은 다음을 구현합니다. Fn특성. 따라서 다음과 같이 호출 할 수 있습니다.() 통사론.

closure_function(parameter);    //invoking

삽화

다음 예제는 main () 함수 내에서 is_even 클로저를 정의합니다 . 클로저는 숫자가 짝수이면 true를 반환하고 숫자가 홀수이면 false를 반환합니다.

fn main(){
   let is_even = |x| {
      x%2==0
   };
   let no = 13;
   println!("{} is even ? {}",no,is_even(no));
}

산출

13 is even ? false

삽화

fn main(){
   let val = 10; 
   // declared outside
   let closure2 = |x| {
      x + val //inner function accessing outer fn variable
   };
   println!("{}",closure2(2));
}

주 () 함수는 변수 선언 과 폐쇄. 클로저는 외부 함수 main ()에 선언 된 변수에 액세스합니다 .

산출

12

Rust는 기본적으로 모든 것을 스택에 할당합니다. Box 와 같은 스마트 포인터로 포장하여 힙에 물건을 저장할 수 있습니다 . Vec 및 String과 같은 유형은 암시 적으로 힙 할당을 돕습니다. 스마트 포인터는 아래 표에 나열된 특성을 구현합니다. 스마트 포인터의 이러한 특성은 일반 구조체와 구별됩니다.

Sr. 아니요 특성 이름 패키지 및 설명
1 Deref

std::ops::Deref

* v와 같은 변경 불가능한 역 참조 작업에 사용됩니다.

2 하락

std::ops::Drop

값이 범위를 벗어날 때 일부 코드를 실행하는 데 사용됩니다. 소멸자 라고도합니다.

이 장에서 우리는 Box스마트 포인터. 또한 Box와 같은 사용자 지정 스마트 포인터를 만드는 방법도 배웁니다.

상자

상자라고도하는 상자 스마트 포인터를 사용하면 스택이 아닌 힙에 데이터를 저장할 수 있습니다. 스택에는 힙 데이터에 대한 포인터가 포함됩니다. Box에는 데이터를 힙에 저장하는 것 외에 성능 오버 헤드가 없습니다.

상자를 사용하여 힙에 i32 값을 저장하는 방법을 살펴 보겠습니다.

fn main() {
   let var_i32 = 5; 
   //stack
   let b = Box::new(var_i32); 
   //heap
   println!("b = {}", b);
}

산출

b = 5

변수가 가리키는 값에 액세스하려면 역 참조를 사용하십시오. *는 역 참조 연산자로 사용됩니다. Box에서 역 참조를 사용하는 방법을 살펴 보겠습니다.

fn main() {
   let x = 5; 
   //value type variable
   let y = Box::new(x); 
   //y points to a new value 5 in the heap

   println!("{}",5==x);
   println!("{}",5==*y); 
   //dereferencing y
}

변수 x는 값이 5 인 값 유형입니다. 따라서 표현식 5 == x 는 true를 반환합니다. 변수 y는 힙을 가리 킵니다. 힙의 값에 액세스하려면 * y를 사용하여 역 참조해야합니다 . * y 는 값 5를 반환합니다. 따라서 표현식 5 == * y 는 true를 반환합니다.

산출

true
true

일러스트-Deref Trait

표준 라이브러리에서 제공하는 Deref 특성을 사용하려면 self 를 빌려 내부 데이터에 대한 참조를 반환하는 deref 라는 하나의 메서드를 구현해야 합니다. 다음 예제 는 일반 유형 인 MyBox 구조를 작성합니다 . Deref 특성을 구현합니다 . 이 특성은 * y를 사용하여 y로 래핑 된 힙 값에 액세스하는 데 도움이됩니다 .

use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> { 
   // Generic structure with static method new
   fn new(x:T)-> MyBox<T> {
      MyBox(x)
   }
}
impl<T> Deref for MyBox<T> {
   type Target = T;
   fn deref(&self) -> &T {
      &self.0 //returns data
   }
}
fn main() {
   let x = 5;
   let y = MyBox::new(x); 
   // calling static method
   
   println!("5==x is {}",5==x);
   println!("5==*y is {}",5==*y); 
   // dereferencing y
   println!("x==*y is {}",x==*y);
   //dereferencing y
}

산출

5==x is true
5==*y is true
x==*y is true

일러스트-Drop Trait

Drop 특성에는 drop () 메서드 가 포함되어 있습니다 . 이 속성을 구현 한 구조가 범위를 벗어날 때이 메서드가 호출됩니다. 일부 언어에서는 프로그래머가 스마트 포인터 인스턴스 사용을 마칠 때마다 메모리 또는 리소스를 해제하기 위해 코드를 호출해야합니다. Rust에서는 Drop 특성을 사용하여 자동 메모리 할당 해제를 수행 할 수 있습니다.

use std::ops::Deref;

struct MyBox<T>(T);
impl<T> MyBox<T> {
   fn new(x:T)->MyBox<T>{
      MyBox(x)
   }
}
impl<T> Deref for MyBox<T> {
   type Target = T;
      fn deref(&self) -< &T {
      &self.0
   }
}
impl<T> Drop for MyBox<T>{
   fn drop(&mut self){
      println!("dropping MyBox object from memory ");
   }
}
fn main() {
   let x = 50;
   MyBox::new(x);
   MyBox::new("Hello");
}

위의 예에서 drop 메서드는 힙에 두 개의 개체를 만들 때 두 번 호출됩니다.

dropping MyBox object from memory
dropping MyBox object from memory

동시 프로그래밍에서 프로그램의 다른 부분은 독립적으로 실행됩니다. 반면에 병렬 프로그래밍에서는 프로그램의 다른 부분이 동시에 실행됩니다. 더 많은 컴퓨터가 다중 프로세서를 활용하므로 두 모델 모두 똑같이 중요합니다.

스레드

스레드를 사용하여 코드를 동시에 실행할 수 있습니다. 현재 운영 체제에서 실행되는 프로그램의 코드는 프로세스에서 실행되고 운영 체제는 여러 프로세스를 한 번에 관리합니다. 프로그램 내에서 동시에 실행되는 독립적 인 부품을 가질 수도 있습니다. 이러한 독립 부품을 실행하는 기능을 스레드라고합니다.

스레드 생성

그만큼 thread::spawn함수는 새 스레드를 만드는 데 사용됩니다. spawn 함수는 클로저를 매개 변수로 사용합니다. 클로저는 스레드가 실행해야하는 코드를 정의합니다. 다음 예제는 메인 스레드의 일부 텍스트와 새 스레드의 다른 텍스트를 인쇄합니다.

//import the necessary modules
use std::thread;
use std::time::Duration;

fn main() {
   //create a new thread
   thread::spawn(|| {
      for i in 1..10 {
         println!("hi number {} from the spawned thread!", i);
         thread::sleep(Duration::from_millis(1));
      }
   });
   //code executed by the main thread
   for i in 1..5 {
      println!("hi number {} from the main thread!", i);
      thread::sleep(Duration::from_millis(1));
   }
}

산출

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 4 from the main thread!

주 스레드는 1에서 4까지의 값을 인쇄합니다.

NOTE− 메인 스레드가 끝나면 새 스레드가 중지됩니다. 이 프로그램의 출력은 매번 조금씩 다를 수 있습니다.

그만큼 thread::sleep함수는 스레드가 짧은 기간 동안 실행을 중지하도록 강제하여 다른 스레드가 실행되도록합니다. 스레드는 번갈아 가며 수행되지만 보장되지는 않습니다. 운영 체제가 스레드를 예약하는 방법에 따라 다릅니다. 이 실행에서는 생성 된 스레드의 print 문이 코드에서 먼저 나타나더라도 주 스레드가 먼저 인쇄됩니다. 더욱이, 생성 된 스레드가 9까지 값을 인쇄하도록 프로그래밍 된 경우에도 주 스레드가 종료되기 전에는 5가됩니다.

핸들 결합

생성 된 스레드는 완전히 실행되거나 실행되지 않을 수 있습니다. 이는 주 스레드가 빠르게 완료되기 때문입니다. 함수 스폰 <F, T> (F : F) -> JoinHandlelt; T는> JoinHandle 반환. JoinHandle 의 join () 메서드는 관련 스레드가 완료 될 때까지 기다립니다.

use std::thread;
use std::time::Duration;

fn main() {
   let handle = thread::spawn(|| {
      for i in 1..10 {
         println!("hi number {} from the spawned thread!", i);
         thread::sleep(Duration::from_millis(1));
      }
   });
   for i in 1..5 {
      println!("hi number {} from the main thread!", i);
      thread::sleep(Duration::from_millis(1));
   }
   handle.join().unwrap();
}

산출

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 2 from the main thread!
hi number 3 from the spawned thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!

메인 스레드와 생성 된 스레드는 계속 전환됩니다.

NOTE − 메인 스레드는 생성 된 스레드가 완료 될 때까지 기다립니다. join() 방법.