Цикл for с if

57 views
Skip to first unread message

ibx

unread,
Oct 21, 2015, 8:27:42 AM10/21/15
to Rust по-русски
Пытаюсь проделать нечто аналогичное в Rust: через цикл, итератор.
Результат нулевой, причём ошибки на уровне азов.
Имеем массив или срез булевых значений, на выходе нужно получить число, сам массив (срез) не изменяем.
Подскажите пожалуйста наиболее рациональный способ как это проделать.

Для примера в С:

#include <stdio.h>
#define SIZE 8

int main(void)
{
    _Bool bitsin [SIZE] = {1,1,0,0,0,0,1,0};
    unsigned char byout = 0;
    unsigned char just = 1;
    unsigned char ri ;
    for (ri = 0; ri <= SIZE; ri++)
        if (bitsin[ri]==1)
            byout = byout | (just << ri);
    printf("%u\n",byout);
    return 0;
}

Andrey Lesnikov

unread,
Oct 21, 2015, 8:45:32 AM10/21/15
to Rust по-русски
Если буквально перевести на ржавчину, то будет


fn main() {
    let bitsin = [true, true, false, false, false, false, true, false];
    let mut byout = 0;
    let just = 1;
    for ri in 0 .. bitsin.len() {
        if bitsin[ri] {
               byout = byout | (just << ri);
        }
    }
    println!("{}", byout);
}



среда, 21 октября 2015 г., 15:27:42 UTC+3 пользователь ibx написал:

Vladimir Matveev

unread,
Oct 21, 2015, 8:50:31 AM10/21/15
to ibx, Rust по-русски
Добрый день!

Следующая программа делает то, что вам нужно:

fn main() {
const SIZE: usize = 8;
let bits_in: [bool; SIZE] = [true, true, false, false, false, false, true, false];

let result = bits_in.iter() // итератор элементов &bool
.enumerate() // итератор элементов (usize, &bool), где первое число - индекс
.fold(0, |acc, (n, &b)| acc + if b { 1 << n } else { 0 });

println!("{}", result);
}

Кстати, вы в курсе, что в вашей программе ошибка выхода за границы массива?

> for (ri = 0; ri <= SIZE; ri++)
> if (bitsin[ri]==1)

Здесь цикл от 0 до SIZE включительно по массиву размера SIZE; последний индекс будет указывать за границу массива.

Код на Rust выше использует итераторы; но то же самое можно сделать и обычным циклом:

fn main() {
const SIZE: usize = 8;
let bits_in: [bool; SIZE] = [true, true, false, false, false, false, true, false];

let mut result = 0;
for (n, &b) in bits_in.iter().enumerate() {
if b {
result |= 1 << n;
}
}

println!("{}", result);
}

Или даже так:

fn main() {
const SIZE: usize = 8;
let bits_in: [bool; SIZE] = [true, true, false, false, false, false, true, false];

let mut result = 0;
for n in 0..SIZE {
if bits_in[n] {
result |= 1 << n;
}
}

println!("{}", result);
}

Но вариант с итераторами (самый первый) более идиоматичный. Кроме того, при проходе по итератору нет проверок выхода за границы массива при получении каждого элемента - это скрыто в самих итераторах. С доступом по индексу проверка выхода индекса за границы будет делаться всегда, хотя в данном случае очень вероятно, что в --release-режиме LLVM её выкинет.
> --
> Вы получили это сообщение, поскольку подписаны на группу "Rust по-русски".
> Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес rust-russian...@googlegroups.com.
> Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/rust-russian/e6c0b9f5-e8de-4d48-8c05-1db6f13ff8fa%40googlegroups.com.
> Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.
> --
> Вы получили это сообщение, поскольку подписаны на группу "Rust по-русски".
> Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес rust-russian...@googlegroups.com.
> Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/rust-russian/e6c0b9f5-e8de-4d48-8c05-1db6f13ff8fa%40googlegroups.com.
> Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

ibx

unread,
Oct 22, 2015, 5:58:58 AM10/22/15
to Rust по-русски

Большое спасибо. 

Reply all
Reply to author
Forward
0 new messages