Форум программистов, компьютерный форум, киберфорум
Rust
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
1

Чтение входного потока

13.06.2020, 22:30. Показов 1893. Ответов 17
Метки rust (Все метки)

Захотелось попробовать Rust в решение простеньких задачек, но удобного ввода данных не нашлось, пришлось своё городить.

Спёр идею, но сделал по своему. В целом, оно работает, но хотелось бы не вычитывать весь входной поток а читать кусками. Приглянулось другое решение, но оно с unsafe.. Я только только закончил 10ю главу книги и, такое ощущение, что чего-то не понимаю.

Есть ли вариант переписать код не усложняя неизвестными конструкциями при этом ускорив работу ? Интересует именно Scanner. (я не выкинул из стуктуры BufRead потому как всё ещё питаю надежды читать из входного потока частями).

Код
use std::io::{self, stdin, BufRead};
use std::fs::File;
use std::str::FromStr;

fn solve<I: BufRead>(mut scan: Scanner<I>) {
	let n: usize = scan.next();
	let a: Vec<i32> = (0..n).map(|_| scan.next::<i32>()-1).collect();
	println!("{} {:?}", n, a);
	// ...
}

fn main() {
    // let input = stdin();
	// let mut input = input.lock();
	// let mut input = io::BufReader::new(File::open("stdin").unwrap());
	let mut input = io::Cursor::new(b"8\n2 3 4 1 1 5 2 7");
	let mut scan = Scanner::from(input);
	solve(scan);
}

struct Scanner<I> {
	input: I,
	bytes: Vec<u8>,
}

impl<I: BufRead> From<I> for Scanner<I> {
	fn from(mut input: I) -> Self {
		let mut bytes: Vec<u8> = Vec::new();
		input.read_to_end(&mut bytes);
		bytes.reverse();
		Self { bytes, input }
	}
}

impl<I: BufRead> Scanner<I> {
	fn next<T: FromStr>(&mut self) -> T {
		let mut bytes: Vec<u8> = Vec::new();
		while let Some(byte) = self.bytes.pop() {
			if !(byte as char).is_whitespace() {
				bytes.push(byte);
				break;
			}
		}
		while let Some(byte) = self.bytes.pop() {
			if (byte as char).is_whitespace() { 
				break 
			}
			bytes.push(byte);
		}
		let token = String::from_utf8(bytes).expect("from_utf8");
		token.parse().ok().expect(format!("parse [{}]", token).as_str())
	}
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.06.2020, 22:30
Ответы с готовыми решениями:

Быстрое чтение чисел из потока
Помогите написать функцию быстрого чтения целых чисел из потока. Уже есть чтение натуральных. ...

Чтение файла из входного потока
есть код в нем есть путь к файлу, как мне сделать так чтоб я не писал путь к файлу а данные...

Чтение данных из входного потока сокета
Всем привет! s = new Socket(this.parametersModbusTCP.getIpAddress(),...

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

__________________
17
Заблокирован
13.06.2020, 23:36 2
есть метод read. определяйте буфер нужной вам величины с помощью массива и читайте туда байты кусками какими вам надо.
0
4135 / 2712 / 388
Регистрация: 01.06.2013
Сообщений: 5,713
Записей в блоге: 9
17.06.2020, 12:07 3
Может читать по строкам через BufRead (если уж хочется читать частями), а строки парсить как строки (str)?
Код
use std::io::{self, BufRead};

fn main() {
	let mut input = io::Cursor::new(b"8\n2 3 4 1 1 5 2 7");
	let mut buf = String::new();
	
	input.read_line(&mut buf);
	let n: usize = buf.trim().parse().unwrap();
	buf.clear();

	input.read_line(&mut buf);
	let a: Vec<i32> = buf.split_whitespace().map(|s| (str::parse::<i32>)(s).unwrap()).collect();
	println!("{} {:?}", n, a);
}
В struct Scanner можно хранить BufReader и ещё не распасрсеные слова в виде строк из последней считанной c помощью read_line строки.
0
Заблокирован
20.08.2020, 14:34 4
Curry, используя метод read из Read можно хоть по одному байту читать, но это будет связано с постоянными системными вызовами. Можно и использовать BufRead, тогда сразу прочитается большим куском - по дефолту 8kb. Не совсем понятно чего хотел автор вопроса и чего сколько прочитать ему надо.

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use std::io;
use std::io::prelude::*;
use std::fs::File;
 
fn main() -> io::Result<()> {
    let mut f = File::open("foo.txt")?;
    let mut buffer = [0; 10];
 
    // read up to 10 bytes
    f.read(&mut buffer)?;
 
    let mut buffer = Vec::new();
    // read the whole file
    f.read_to_end(&mut buffer)?;
 
    // read into a String, so that you don't need to do the conversion.
    let mut buffer = String::new();
    f.read_to_string(&mut buffer)?;
 
    // and more! See the other methods for more details.
    Ok(())
}
Можно вообще читать строки просто, если это stdin и потом разбивать их на нужные куски.

C++ (Qt)
1
2
3
4
5
6
use std::str;
 
fn main() {
  let x = &"Привет, Мир"[..12].as_bytes();
  println!("{}", str::from_utf8(&x).unwrap());
}
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
07.09.2020, 18:35  [ТС] 5
Цитата Сообщение от sodda Посмотреть сообщение
"Привет, Мир"
Не 12 байт и то что from_utf8(&x).unwrap() не крашнуло это большое счастье.
0
Заблокирован
07.09.2020, 18:40 6
Цитата Сообщение от outoftime Посмотреть сообщение
Не 12 байт и то что from_utf8(&x).unwrap() не крашнуло это большое счастье.
"Привет" - это 12 байт.

Добавлено через 1 минуту
Цитата Сообщение от outoftime Посмотреть сообщение
не крашнуло это большое счастье.
Не крашнится, так как from_utf8() возвращает Result. А построить юникод-строку из неправильной последовательности байт функция не может - возврати ошибку.
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
07.09.2020, 19:00  [ТС] 7
Цитата Сообщение от sodda Посмотреть сообщение
используя метод read из Read можно хоть по одному байту читать, но это будет связано с постоянными системными вызовами. Можно и использовать BufRead, тогда сразу прочитается большим куском - по дефолту 8kb. Не совсем понятно чего хотел автор вопроса и чего сколько прочитать ему надо.
Я всё больше тащусь от макросов спёртых у японцев. Задача читать входной поток на соревновательных площадках типа codeforces.

Код
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}
 
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};
 
    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}
 
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };
 
    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };
 
    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };
 
    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };
 
    ($next:expr, [ $t:tt ]) => {{
        let len = read_value!($next, usize);
        (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    }};
 
    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}
Добавлено через 1 минуту
Цитата Сообщение от sodda Посмотреть сообщение
возврати ошибку
Вот
Код
use std::str;
 
fn main() {
  let x = &"Привет, Мир"[..11].as_bytes();
  println!("{}", str::from_utf8(&x).unwrap());
}
Разница в том что 11 байт а не 12. "Возрати ошибку" так смешно.
1
Заблокирован
07.09.2020, 19:13 8
Цитата Сообщение от outoftime Посмотреть сообщение
Разница в том что 11 байт а не 12. "Возрати ошибку" так смешно.
Нет, просто вы думаете, что длинна всей строки - "Привет, Мир" - это 11 байт, что уже неправильно.
Это не ASCII, а юникод и кириллический знак весит два байта. 12 байт - это как раз будет словом "Привет".
0
Миниатюры
Чтение входного потока   Чтение входного потока  
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
10.09.2020, 00:13  [ТС] 9
sodda, без байткода не понять это кириллица или что-то ещё.
0
Заблокирован
10.09.2020, 00:24 10
Цитата Сообщение от outoftime Посмотреть сообщение
sodda, без байткода не понять это кириллица или что-то ещё.
Кириллица а что же еще. ASCII только латинские буквы включает.
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
10.09.2020, 01:05  [ТС] 11
Цитата Сообщение от sodda Посмотреть сообщение
Кириллица а что же еще
Смотря какой шрифт
0
3293 / 2355 / 425
Регистрация: 28.04.2012
Сообщений: 7,854
10.09.2020, 23:36 12
outoftime,

Код
use std::str;

fn main() {
    let x = &"Привет, Мир"[..12].as_bytes();
    let s = str::from_utf8(&x).unwrap();

    let mut utf8  : [u8; 2] = [0,0];
    let mut utf16 : [u16;1] = [0];
    for c in s.chars() {
        c.encode_utf8(&mut utf8);
        c.encode_utf16(&mut utf16);
        println!("{}  -  UTF8: {:08b} {:08b}  ->  0000 {:06b} {:06b}  ->  UTF16: {:016b}  ->  Unicode: {:04x}",
                 c, utf8[0], utf8[1], utf8[0] & 0b111111, utf8[1] & 0b111111, utf16[0], utf16[0]);
    }

    println!("{}", s);
}
Код
П  -  UTF8: 11010000 10011111  ->  0000 010000 011111  ->  UTF16: 0000010000011111  ->  Unicode: 041f
р  -  UTF8: 11010001 10000000  ->  0000 010001 000000  ->  UTF16: 0000010001000000  ->  Unicode: 0440
и  -  UTF8: 11010000 10111000  ->  0000 010000 111000  ->  UTF16: 0000010000111000  ->  Unicode: 0438
в  -  UTF8: 11010000 10110010  ->  0000 010000 110010  ->  UTF16: 0000010000110010  ->  Unicode: 0432
е  -  UTF8: 11010000 10110101  ->  0000 010000 110101  ->  UTF16: 0000010000110101  ->  Unicode: 0435
т  -  UTF8: 11010001 10000010  ->  0000 010001 000010  ->  UTF16: 0000010001000010  ->  Unicode: 0442
Привет
https://unicode.org/charts/PDF/U0400.pdf
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
11.09.2020, 19:18  [ТС] 13
korvin_, "Мaмa мылa рaмy" это кирилица?
0
3293 / 2355 / 425
Регистрация: 28.04.2012
Сообщений: 7,854
11.09.2020, 20:32 14
Цитата Сообщение от outoftime Посмотреть сообщение
"Мaмa мылa рaмy" это кирилица?
Ты сам-то как думаешь? https://play.rust-lang.org/?ve... 85c29173f3
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
14.09.2020, 13:16  [ТС] 15
Цитата Сообщение от korvin_ Посмотреть сообщение
Ты сам-то как думаешь?
Писал уже выше - зависит от шрифта.
0
3293 / 2355 / 425
Регистрация: 28.04.2012
Сообщений: 7,854
14.09.2020, 19:07 16
Цитата Сообщение от outoftime Посмотреть сообщение
Писал уже выше - зависит от шрифта.
Не зависит. string ничего не знает ни о каких шрифтах, а по ссылке, что я дал — список Unicode'ных code-point'ов.
0
║XLR8║
1105 / 852 / 256
Регистрация: 25.07.2009
Сообщений: 4,180
Записей в блоге: 5
14.09.2020, 21:04  [ТС] 17
Цитата Сообщение от korvin_ Посмотреть сообщение
string ничего не знает ни о каких шрифтах
Как и ты не знаешь ничего о string ибо смотришь на шрифты.

Цитата Сообщение от korvin_ Посмотреть сообщение
я дал — список Unicode'ных code-point'ов
Ага, сплю и вижу как ты текст читаешь в "Unicode'ных code-point'ах"
0
3293 / 2355 / 425
Регистрация: 28.04.2012
Сообщений: 7,854
14.09.2020, 23:22 18
Цитата Сообщение от outoftime Посмотреть сообщение
Как и ты не знаешь ничего о string ибо смотришь на шрифты.
О чём ты вообще?

Цитата Сообщение от outoftime Посмотреть сообщение
Ага, сплю и вижу как ты текст читаешь в "Unicode'ных code-point'ах"
что с тобой не так?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.09.2020, 23:22

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Очистка входного потока
Здравствуйте уважаемые! Пишу игрушку на C#, возникла проблема: в одном месте (в меню выбора...

Слова входного потока
Вывести самые длинные слова входного потока! если во вх потоке самое длинное слово одно,то...

Прочитать все из входного потока
Начал учиться программировать на c#, решая задачки на сайте олимпиадного программирования. Сразу же...

Считывание до конца входного потока
Что значит считывание данных до конца входного потока? Знаю, что на C++ реализуется так. А что...

Проверка входного потока на ошибки
Ребяты подскажите плз )))) сам не как не разберусь можно ли использовать failbit badbit goodbit...

Работа стандартного входного потока
Здравствуйте. Допустим есть код: int number1, number2; std::cin &gt;&gt; number1 &gt;&gt; number2; Мы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.