LINUX.ORG.RU

Таймер на Rust/C/C++

 , ,


0

3

Привет!

В общем, задачка такая:
Как сделать таймер на раст в минутах, который каждую минуту будет давать выхлоп о том, сколько минут осталось? Вроде код простой, но все найденные библиотеки считают в лучшем случае в секундах

Например в терминале пишем:

нашапрограмма 90

Через минуту выхлоп:

89

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

Спасибо!

★★

Последнее исправление: admucher (всего исправлений: 2)

По теме больше для job подходит.

vvn_black ★★★★★
()

Вроде код простой, но все найденные библиотеки считают в лучшем случае в секундах

Можно секунды поделить на 60.

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

Можно секунды поделить на 60.

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

use tokio::time::delay_for;

use std::time::Duration;


#[tokio::main]
async fn main() {
    delay_for(Duration::from_secs(60)).await;
    println!("60");
}

Прикрутить к нему чтение внешнего значения, калькулятор и зациклить, но это говнокод какой-то будет, который можно сделать и на bash\cmd)

admucher ★★
() автор топика
use std::env;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut query = &args[1];
    // Create channels for sending and receieving
    let (one_tx, one_rx) = channel();

    // Spawn timer
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_secs(60));
            one_tx.send(query).unwrap();
            query = query-1;
            if query == 0 { break; }
        }
    });

    loop {
        thread::sleep(Duration::from_millis(50));
        let _ = one_rx.try_recv().map(|reply| println!("{}", reply));
    }
}

Рейт.

kogoth
()
Ответ на: комментарий от kogoth

Клево, но не собирается(

error[E0369]: cannot subtract `{integer}` from `&std::string::String`
  --> src\main.rs:17:26
   |
17 |             query = query-1;
   |                     -----^- {integer}
   |                     |
   |                     &std::string::String

error[E0277]: can't compare `&std::string::String` with `{integer}`
  --> src\main.rs:18:22
   |
18 |             if query == 0 { break; }
   |                      ^^ no implementation for `&std::string::String == {integer}`
   |
   = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&std::string::String`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0369.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `timer`.
admucher ★★
() автор топика

Стандартная библиотека

use std::time::Duration;

fn main() {
    let sleep_duration = Duration::from_secs(1);
    for minutes_left in (1..61).rev() {
        println!("{}",minutes_left);
        std::thread::sleep(sleep_duration);
    }
}

Асинхронные прибамбасы

use std::time::Duration;
use tokio::time::delay_for;

#[tokio::main]
async fn main() {
    let sleep_duration = Duration::from_secs(1);
    for minutes_left in (1..61).rev() {
        println!("{}",minutes_left);
        delay_for(sleep_duration).await;
    }
}
vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 3)
Ответ на: комментарий от admucher

Да, забыл аргумент в int перевести

use std::env;
use std::str::FromStr;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut query = i32::from_str(&args[1]).unwrap_or(0);
    // Create channels for sending and receieving
    let (one_tx, one_rx) = channel();

    // Spawn timer
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_secs(60));
            one_tx.send(query).unwrap();
            query = query-1;
            if query == 0 { break; }
        }
    });

    loop {
        thread::sleep(Duration::from_millis(50));
        let _ = one_rx.try_recv().map(|reply| println!("{}", reply));
    }
}

kogoth
()
Ответ на: комментарий от vertexua
use std::time::Duration;

fn main() {
    let sleep_duration = Duration::from_secs(1);
    for minutes_left in (1..61).rev() {
        println!("{}",minutes_left);
        std::thread::sleep(sleep_duration);
    }
}

Работает, и код меньше, чем ожидал! Но from_secs надо на 60 изменить)
А как получить minutes_left из вне? Например, пишу в терминал

timerminutes 50

admucher ★★
() автор топика
Ответ на: комментарий от kogoth

Спасибо. Запустился и работает как надо, вот только по истечению времени не выходит из программы)

admucher ★★
() автор топика
Ответ на: комментарий от admucher
use std::env;
use std::process;
use std::str::FromStr;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut query = i32::from_str(&args[1]).unwrap_or(0);
    // Create channels for sending and receieving
    let (one_tx, one_rx) = channel();

    // Spawn timer
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_secs(60));
            query = query - 1;
            one_tx.send(query).unwrap();
            if query == 0 { process::exit(1);}
        }
    });

    loop {
        thread::sleep(Duration::from_millis(50));
        let _ = one_rx.try_recv().map(|reply| println!("{}", reply));
    }
}

P.S. Чтобы получить аргумент 50 извне, нужно подключить std::env и std::str::FromStr и в from_secs(1) вместо единицы поместить query, если брать мои названия.

kogoth
()
Ответ на: комментарий от trex6

Без дополнительной коррекции на больших отрезках времени будет отставать же.

Отставать будет в любом случае. Многозадачность, вся фигня.

hateyoufeel ★★★★★
()
Ответ на: комментарий от kogoth

Если вы про этот код

use std::time::Duration;

fn main() {
    let sleep_duration = Duration::from_secs(1);
    for minutes_left in (1..61).rev() {
        println!("{}",minutes_left);
        std::thread::sleep(sleep_duration);
    }
}

то тут from_secs должно быть 60 (интервал вывода, т.е. каждую минуту). В нем надо получать из вне minutes_left.

В моем случае получилось вот так:

use std::env;
use std::str::FromStr;
use std::time::Duration;

fn main() {
	let args: Vec<String> = env::args().collect();
    let query = i32::from_str(&args[1]).unwrap_or(0);
    let sleep_duration = Duration::from_secs(60);
    for minutes_left in (0..query).rev() {
	std::thread::sleep(sleep_duration);
        println!("{}",minutes_left);
    }
}

Спасибо kogoth и vertexua!

admucher ★★
() автор топика
Ответ на: комментарий от xpahos

в моем случае самый правильный способ это такой))

set /p time=
:timer
timeout 60
set /a time=time - 1
echo %time%
goto timer
admucher ★★
() автор топика

Ахренеть как в вашем этом расте все сложно. Ну как правильные посоны (хехе) с телеграм каналов по расту говорят: «поищи нужный крат».

anonymous
()
Ответ на: комментарий от trex6

Тут ошибка будет накапливаться. Особенно если по таймеру какая-то работа будет выполнятся.

Ага. Поэтому sleep() в треде – это паршивая идея для таймера.

hateyoufeel ★★★★★
()
Ответ на: комментарий от trex6

Он не сказал что нужно таким запариваться, может он через эту штуку что-то в духовке запекает )

vertexua ★★★★★
()
Ответ на: комментарий от admucher

Зависит от того, что у тебя происходит в коде. Если просто вывод строки, то можно забить. Если что-то более долгое, тебе стоит задуматься.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Ничего. Весь код в моем сообщении благодарностей) Нужен был тупо таймер, а его уже подтягивает тот, кому надо

admucher ★★
() автор топика
Ответ на: комментарий от admucher

Дикая дичь же. Я выше скинул ссылку, там можно тупо коллбэк сунуть и он будет вызываться по таймеру.

hateyoufeel ★★★★★
()

Народ занимается изобретением велосипедов. Какие-то крейты дополнительные тянуть предлагает, дополнительные треды заводит с каналами. Когда всё как проще:

use std::env;
use std::thread;
use std::time;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!( "{} <minutes>", args[0] );
        return;
    }
    let query = u64::from_str_radix( &args[1], 10 ).expect( "Incorrect parameter" );
    let sleep_time = time::Duration::from_millis( 500 );
    let now = time::Instant::now();
    let mut minutes = 0u64;
    println!( "Start! {}", query );
    loop{
        thread::sleep( sleep_time );
        let tm = now.elapsed().as_secs() / 60;
        if tm >= query {
            break;
        } else if tm != minutes {
            println!( "minutes {}", tm );
            minutes = tm;
        }
    }

    println!( "minutes {}", query );
    println!( "Stop! {}", query );
}

И самое главное никакого убегания не будет, хоть 100500 минут поставь. Разве что системный таймер навернётся.

На плюсах все примерно так же, попизжа закину.

WatchCat ★★★★★
()
Последнее исправление: WatchCat (всего исправлений: 1)

Пример на 17-х плюсах.

#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>

namespace ch = std::chrono;
namespace th = std::this_thread;

int main(int argc, char *argv[]) {
    using namespace std::chrono_literals;

    if( argc != 2 ){
        std::cerr << argv[0] << " <minutes>" << std::endl;
        return 1;
    }

    std::istringstream ins(argv[1]);
    unsigned query, minutes(0);
    if( !( ins >> query && ins.eof())){
        std::cerr << "Incorrect argument: " << argv[1] << std::endl;
        return 1;
    }
	
    std::cout << "Start! " << query << std::endl;
    auto start = ch::system_clock::now();
    while(true){
        th::sleep_for(500ms);
        auto elapsed = ch::system_clock::now();
        auto tm = ch::duration_cast<ch::minutes>(elapsed - start).count();
        if( tm != minutes ){
            std::cout << "minutes " << tm << std::endl;
            minutes = tm;
        }
        if( minutes >= query ) break;
    }
    std::cout << "Stop! " << query << std::endl;
    return 0;
}

PS Цикл в rust-варианте можно чутка поправить и сделать по аналогии с плюсовым.

WatchCat ★★★★★
()
Последнее исправление: WatchCat (всего исправлений: 1)
Ответ на: комментарий от WatchCat

Class std::chrono::system_clock represents the system-wide real time wall clock.

It may not be monotonic: on most systems, the system time can be adjusted at any moment.

Удачи твоей программе.

unC0Rr ★★★★★
()
Ответ на: комментарий от admucher

Выводи query - tm вместо просто tm. Элементарно же.

WatchCat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.