New We are sorting MAX channels into categories and territories. Read the news
Public channel ID 72073278341637

Записки о Rust

Процесс погружения в rust

Open in MAX

Posts for the period

By reactions

Search and the whole feed — after free registration. Custom dates — with a subscription; the channel owner sees them for free. Sorting by reactions — with a subscription. Sign up

Loading…

Loading image…
В Rust не принято возвращать из функций "чистый" тип, обычно для этого используется перечисление enum. Если говорить о стандартных библиотеках Rust то чаще всего возвращается

pub enum Option<T> {
Some(T),
None,
}

Предполагается, что значение может отсутствовать.

Или

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

для возвращения конкретного результата или ошибки.

Встречаются и другие варианты, в зависимости от того, что должно быть возвращено.

Пример с Option

fn main() {
 let num = vec![1, 2, 3, -10, 143];
 // Возвращает Option<&i32> по индексу
 let res = num.get(4);.
 match res {
     Some(value) => println!("Нашли: {}", value),
     None => println!("Не нашли"),
 }
}

Пример с Result. Кто читал предыдущие посты подобные примеры уже неоднократно встречались.


use std::io;

fn main() {
   let mut input = String::new(); // строка для ввода
   println!("Введите ваше имя:");.
// ввод с клавиатуры с проверкой ошибки с дописывания строки input
   match io::stdin().read_line(&mut input) {
       Ok(n) => {
         println!("Всего {} байтов", n);
         let mut input = "Привет ".to_string() + &input.trim() + &"!".to_string();
         println!("{}", input);
       }
       Err(error) => {
         println!("Ошибка при чтении: {}", error);
       }
   }
}

Обработка с оператором match предпочтительна, но не обязательна. В дальнейшем расскажу о других возможностях.

Описанные выше особенности языка rust входит в его основы. Это следует усвоить.
Views: 40
Go to post Open in MAX Report an inaccuracy
Loading image…
Сегодня тема: ввод с клавиатуры. Две не большие программки.
Одна - это просто ввод с клавиатуры строки, другая ввод с клавиатуры
с последующей попыткой преобразовать строку в целое число.


use std::io;

fn main() {
let mut input = String::new(); // строка для ввода
println!("Введите ваше имя:");.
// ввод с клавиатуры с проверкой ошибки с дописывания строки input
match io::stdin().read_line(&mut input) {
Ok(n) => {
println!("Всего {} байтов", n);
let mut input = "Привет ".to_string() + &input.trim() + &"!".to_string();
println!("{}", input);
}
Err(error) => {
println!("Ошибка при чтении: {}", error);
}
}
}

И так io::stdin().read_line(&mut input) ввод строки с клавиатуры.
Тут важно отметить, метод read_line() добавляет символы в строку,
не очищая её. Поэтому нужно использовать для этой цели
пустую строку. У нас она просто создаётся для этой цели.

Второе. Этот метод возвращает тип перечисление (enum). Поэтому
мы используем match. В зависимости от результата иы выполняем то или иное
действие. Да и не забудем про библиотеку std::io, она нужна для read_line().


В следующем примере мы вводим строку, а потом пытаемся преобразовать
её в число. Поэтому у нас вложенные операторы match.

use std::io;
use std::process;

fn main() {
let mut input = String::new(); // пустая строка
match io::stdin().read_line(&mut input) {
Ok(_) => {
// преобразовать строку в число
let number: i32 = match input.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Вы ввели некорректное значение!");
process::exit(1); // завершаем программу с кодом 1
}
};
}
Err(error) => {
println!("Ошибка при чтении: {}", error);
}
}
}

Внутренний match реагирует на ситуацию когда строка не может быть преобразована
в число. В этом случае программа заканчивает своё выполнение через использование
process::exit(1) - код выхода 1. Чтобы использовать этот метод мы подключили библиотеку
std::process.

Конечно, то что я здесь представил, надо бы обернуть в функции.
Т.е. создать свою библиотечку, которую можно использовать
в разных приложениях. Но об этом поговорим в одном из следующих постов.

Не забывайте, что оглавление по моим постам можно найти здесь

https://dzen.ru/a/aq_S5YWcNkgWfHcO

Оглавление тематическое, а на канале здесь темы идут не по порядку.
Views: 32
Go to post Open in MAX Report an inaccuracy
Loading image…
Loading image…
Сегодня поговорим о параметрах командной строки. Надеюсь, читатель умеет с ней работать. Текст программы parameters00 представлен ниже. Операционная система Alt Linux.

se std::env;

fn main() {
   // Собираем все аргументы в вектор
   let args: Vec<String> = env::args().collect();
// Первый элемент — это путь к исполняемому файлу
   println!("Путь к программе: {}", args[0]);
// Остальные элементы — это переданные параметры
   if args.len() > 1 {
       println!("Переданные прараметры");
       for arg in args[1..].iter() {
           println!("Параметр {}", arg);
       }
   } else {
       println!("Параметры не переданы.");
   }
}

Для работы с параметрами командной строки я использую библиотеку std и её модуль env. args[1..] - это так называемый срез. Метод iter превращает его в итератор, по которому мы проходим с помощью цикла.

Не забывайте, что по адресу

https://dzen.ru/a/aq_S5YWcNkgWfHcO

есть тематическое оглавление моих материалов по Rust.
Views: 39
Go to post Open in MAX Report an inaccuracy
Loading image…
Продолжаем наши изыскания в области языка Rust и функций в частности. Сегодня об анонимных функциях (замыканиях), а также об обобщённых параметрах.

Анонимные функции или замыкания не имеют имени. Их можно определить внутри другой функции. Признаком их являются две вертикальные черты, между которыми указываются параметры. Анонимную функцию можно присвоить переменной и потом использовать в выражениях.

fn main() {
// простая анонимная функция, возведение в степень
 let pwr = |n:i64|{
    n * n
 };
 println!("{}", pwr(33));
// анонимная функция без скобок
// без указания типов параметров
 let sum = |a, b|a+b;
 println!("{}",sum(222, 900));
}

В программе выше определены две анонимные функции. Если выражение в функции однострочное, то можно обойтись без фигурных скобок. Результат выполнения программы

1089
1122

Анонимные функции могут захватывать переменные и их можно передавать в другие функции в качестве параметров.

// функция с обобщённым параметром (F)
fn dv<F>(divi:F, b:i64).
where.
  F:Fn(i64)->&'static str,.
{
  println!("{} {}", divi(b), divi(b+1));
}
fn main() {
// анонимная функция с замыканием (захватом переменной a)
  let a:i64 = 7;
  let div = |n:i64| {
     if n % a == 0 {
       "Делится"
     } else {
       "Не делится"
     }
  };
  println!("{} {}", div(49), div(50));
  dv(div, 56);
}


Что мы видим?
1. Анонимная функция захватывает переменную a.
2. Анонимная функция передаётся в качестве параметра.

Самое интересное, как определяется функция, у которой есть параметр -функция. Важно <F> - мы указываем обобщённый параметр. После слова where указывается какому условию он должен удовлетворять. Таким образом в функцию можно передавать и другие параметры-функции, если они удовлетворяют указанному условию (соответствуют сигнатуре).

Не забываем, что по адресу
https://dzen.ru/a/aq_S5YWcNkgWfHcO

перечислены статьи по Rust, распределённые по темам, которые опубликовал в данном канале.
Views: 35
Go to post Open in MAX Report an inaccuracy
Loading image…
Многомодульные программы.

Как и в любом другом современном языке программирования в Rust
программа может состоять из множества модулей. Если кода много,
то способ упростить программирование.

Я пока не рассказывал об устройстве каталога, где хранится проект на языке Rust.
Но если вы уже пишите программы на Rust, то знаете, что в каьалоге с проектом,
подкаталог src, где и хранится текст (тексты) программы на Rust.
В простейшем случае там хранится один файл main.rs. Но программа может быть большой,
и приходится разбивать её на несколько моделей. А если модулей слишком много,
то приходится в src делать подкаталоги, т.е. в сущности разбивать модели ещё и на
группы. Вот как может быть устроена такая система модулей я и покажу на конкретном
примере.

В начале покажу схему каталогов
src
--conf
--modules
----new

А теперь посмотрим файловое содержимое каталогов
src:
./main.rs
conf:
./mod.rs
modules:
./mod.rs
./modul1.rs
./modul2.rs
new:
./mod.rs

Теперь не много о названиях моделей.
Модуль с именем main - главный модуль проект.
Модули с именем mod это главные модули в конкретном подкаталоге.
Т.е. связь с модулями подкаталога идёт через модули с именами mod.
Ну а теперь модеражимое всех модулей.
=======================
main.rs:
=======================
mod conf;
mod modules;

fn main() {
println!("В главном модуле");
conf::main_in_conf();....
modules::main_in_modules();....
modules::modul1::in_modul1();
modules::modul2::in_modul2();
modules::new::main_in_modules_new
();
}
=======================
conf/mod.rs:
=======================
pub fn main_in_conf() {
println!("В главном модуле каталога conf
");
}
=======================
modules/mod.rs:
=======================
pub mod modul1;.
pub mod modul2;.
pub mod new;

pub fn main_in_modules() {
println!("В главном модуле каталога module
s");
}
=======================
modules/modul1.rs:
=======================
pub fn in_modul1() {
println!("В модуле modules/modul
1");
}
=======================
modules/modul2.rs:
=======================
pub fn in_modul2() {
println!("В модуле modules/modul
2");
}
=======================
modules/new/modul2.rs:
=======================
pub fn main_in_modules_new() {
println!("В главном модуле каталога modules/ne
w");
}

Результат выполнения программы
В главном модуле
В главном модуле каталога conf
В главном модуле каталога modules
В модуле modules/modul1
В модуле modules/modul2
В главном модуле каталога modules/new

Ну вот, пока всё о многомодульности. Но только пока. Вернёмся к этому вопросу позднее.
Views: 107
Go to post Open in MAX Report an inaccuracy
Loading image…
По-старому буду называть эту структуру словарём. Хотя есть ещё одно название "ассоциированный массив". Но вот в rust это называется хэшем.

А смысл в следующем. Это список пар (ключ, значение). В rust все ключи и все значения должны быть одного типа. Хотя как обычно это требование обходится с помощью enum - перечисления. Я об этом расскажу позднее. Ниже представлен пример программы формирования хэша, перебор всех пар и получения значения по ключу.

use std::collections::HashMap;

fn main() {
// задать
   let mut sl = HashMap::new();
// добавить значения
   sl.insert(String::from("Иванов И.И."), 120000);
   sl.insert(String::from("Петров П.П."), 70000);
   sl.insert(String::from("Пупкина З.В."), 80000);
   sl.insert(String::from("Васильев-Задунайский Р.Р."), 90000);
// перебор
   for (name, salary) in &sl {
       println!("{} - {}", name, salary);
   }
// доступ по ключу
   let key = "Пупкина З.В.".to_string();
   match sl.get(&key) {
      Some(&sal) => println!("{} - {}", key,  sal),
      None => println!("{} Нет такого!", key),
   }
}

Не забывайте указать библиотеку для импортирования: use std::collections::HashMap;.

Да, доступ к значению по ключу очень быстрый. Этим и ценна данная структура.
Views: 119
Go to post Open in MAX Report an inaccuracy
Loading image…
Вернёмся к строкам. Рассмотрим теперь как сравнивать строки.
В программе ниже всё понятно. Так что, что не буду отдельно её комментировать.

use std::cmp::Ordering;

fn main() {
// сравнение на равенство
let s1 = "Привет".to_string();
let s2 = "привет".to_string();
if s1 == s2 {
println!("равны");
} else {
println!("не равны");
}
// лексиграфическое сравнение
let s11 = "Привет".to_string();
let s22 = "Привет".to_string();
match s11.cmp(&s22) {
Ordering::Less => println!("s11 < s22"),
Ordering::Equal => println!("s11 == s22"),
Ordering::Greater => println!("s11 > s22"),
}
// сравнение с константой (шаблоном)
let s = "Здравствуйте".to_string();
match s.as_str() {
"Здравствуйте" => println!("Привет"),
"До свидания" => println!("Увидимся"),
_ => println!("????"),
}
}
Views: 78
Go to post Open in MAX Report an inaccuracy
Loading image…
Продолжим о файлах. Следующая программа читает файл (текстовый) и пишет данные в другой файл, который создаётся или перезаписывается.

use std::io::Read;
use std::fs::File;
use std::io::Write;

// открыть для чтения
fn of(ps:&str) -> Result<File, std::io::Error> {
File::open(ps)
}
// создать файл
fn wf(ps:&str) -> Result<File, std::io::Error> {
File::create(ps)
}

fn main() {
let s:String = "./1.txt".to_string();
let s2:String = "./2.txt".to_string();
match of(&s) { // обработка открытия
Ok(mut file) => {
println!("Файл открыт для чтения");
let mut txt = String::new();
match file.read_to_string(&mut txt) { // чтение
Ok(_) => {
match wf(&s2) { // открыть для записи (создать)
Ok(mut file2) => {
match file2.write_all(txt.as_bytes()) { //записать
Ok(_) => println!("Записано"),
Err(_) => println!("Ошибка записи"),
}
},
Err(_) => println!("Ошибка создания"),
}
}
Err(e) => eprintln!("Не удалось прочитать данные из файла: {}", e),
}
},
Err(_e) => {
println!("Ошибка");
}
}
}

В программе должно быть всё понятно, так как подобное уже использовано в предыдущих постах. Да, может смущать вот такая вложенная структура match. Но к упрощению такой записи мы вернёмся позднее, также как позднее мы подробнее обратимся к вопросам управления файлами на Rust.
Views: 49
Go to post Open in MAX Report an inaccuracy
The full feed — after free sign-up
VKontakte Telegram Odnoklassniki
Favorites at datool.ru

Follow the channel in your account

Sign up at datool.ru to add the channel “Записки о Rust” to favorites and track its metrics.

Sign up
For channel owners

Verify your channel

Sign in or sign up at datool.ru, then add our bot to the channel following the instructions in your account. Once ownership is verified, the lock disappears and channel management becomes available.

Sign in or sign up

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go