I want to input a vector of vectors of u32 using the std::io library.
Here is what I did and it obviously doesn't work because the parse method can't turn a String into a Vec:
fn main() {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
let input: Vec<Vec<u32> = match input.trim().parse() {
Ok(num) => num,
Err(_) => vec![vec![0]],
};
}
If you have another way to make it work I'll be happy to try it :)
For an input of the stile:
1 2 3 4
5 6 7 8
You could use something like the following example. Notice the use of BufRead
use std::io::BufRead;
fn read_input() -> std::io::Result<Vec<Vec<u64>>> {
let stdin = std::io::stdin();
let mut lines = stdin.lock().lines();
let mut res = Vec::new();
while let Some(line) = lines.next() {
let line = line?;
let items = line
.split(" ")
.map(|n| n.parse().expect("an u64 parseable number"))
.collect();
res.push(items);
}
Ok(res)
}
Playground
Related
Good afternoon!
I have some configured vector by type:
let v = vec!["foo", "bar", "go", "any"];
How can I output the contents of a vector to a text file with the addition of something to the line?
What I want to get in the text file:
foo#gmail.com
bar#gmail.com
go#gmail.com
any#gmail.com
Options I have tried:
use std::{fs::File, io::Write};
fn main() -> std::io::Result<()> {
let v = vec!["foo", "bar", "go", "any"];
let mut f = File::create("try.txt")?;
for item in v {
f.write_all(item.as_bytes())?;
}
Ok(())
}
The final code looked like this:
use std::{fs::File, io, io::Write};
fn main() -> std::io::Result<()> {
let v = vec!["foo", "bar", "go", "any"];
let mut write_domain = String::new();
println!("Enter your domain :");
let _user_domain = io::stdin().read_line(&mut write_domain).unwrap();
let mut f = File::create("try.txt")?;
for item in v {
let item = format!("{item}#{write_domain}");
f.write_all(item.as_bytes())?;
}
Ok(())
}
What a high ego people have, be kinder.
Thank you very much in advance
It would be simpler if you joined the vector first into one string and then write it all at once :
use std::fs::File;
use std::io::{stdin, Write};
fn main() {
let emails = vec!["foo", "bar", "go", "any"];
let mut write_domain = String::new();
stdin().read_line(&mut write_domain).unwrap();
let text = emails
.iter()
.map(|name| format!("{name}#{write_domain}"))
.collect::<Vec<String>>()
.join("\n");
let mut f = File::create("try.txt").unwrap();
f.write_all(text.as_bytes()).unwrap();
}
i have a simple txt file with one value per line.
Is it somehow possible to compare two lines?
I was looking for a way to index each line and then compare the index [n] with index [n+1].
By now i am able to print each line, but not to compare the entries.
Here is my code:
use std::fs::File;
use std::env;
use std::io::{self, BufReader, BufRead};
fn read_file(filename: &String) -> io::Result<()> {
let file = File::open(filename)?;
let content = BufReader::new(file);
for line in content.lines() {
println!("{}", line.unwrap());
}
Ok(())
}
fn main() {
let args: Vec<String> = env::args().collect();
let filename = &args[1];
read_file(filename).expect("error reading file");
}
One solution is to collect all lines into a vector and use std::iter::zip method.
fn read_file(filename: &String) -> io::Result<()> {
let file = File::open(filename)?;
let content = BufReader::new(file);
let lines: Vec<String> = content
.lines()
.map(|line| line.expect("Something went wrong"))
.collect();
for (current, next) in lines.iter().zip(lines.iter().skip(1)) {
println!("{}, {}", current, next)
}
Ok(())
}
So for the input file having content,
1
2
3
4
read_file function will print
1, 2
2, 3
3, 4
I'd like to find a keyword in a text file or in a variable. I want to get user input and paste it into a text file.
my code:
use std::fs;
fn main() {
let mut user_name = String::new();
println!("Hello what is your name: ");
std::io::stdin().read_line(&mut name).unwrap();
fs::write("files/user_name.txt", user_name).unwrap();
let mut user_wish = String::new();
println!("What is your wish: ");
std::io::stdin().read_line(&mut user_wish).unwrap();
fs::write("files/user_wish.txt", user_wish).unwrap();
}
I don't know how to find keywords like my and name in the text file user_wish.txt so that I can list user_name.
use std::fs;
static KEYWORDS: &'static [&'static str] = &["my", "name"];
fn main() {
let mut user_name = String::new();
println!("Hello what is your name: ");
std::io::stdin().read_line(&mut user_name).unwrap();
// ---
// fs::write<P, C>(path: P, contents: C)
// -- Note contents takes ownership of `C` / `user_clone`
// that memory will be consumed after it finishes
// so we give it clone(), so we can still access `user_name`
fs::write("files/user_name.txt", user_name.clone()).unwrap();
for kword in KEYWORDS {
if user_name.contains(kword) {
println!("contains keyword");
}
}
let mut user_wish = String::new();
println!("What is your wish: ");
std::io::stdin().read_line(&mut user_wish).unwrap();
fs::write("files/user_wish.txt", user_wish).unwrap();
}
My input data is structured as follows:
label_1
value_1
label_2
value_2
...
And my end goal is to read that data into a HashMap
My current working approach is to put even and odd lines in two separate vectors and then read from both vectors to add to Hashmap.
use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
fn main() {
let mut labels: Vec<String> = Vec::new();
let mut values: Vec<String> = Vec::new();
let stdin = io::stdin();
/* Read lines piped from stdin*/
for (i, line) in stdin.lock().lines().enumerate() {
if i % 2 == 0 {
/* store labels (even lines) in labels vector */
labels.push(line.unwrap());
} else {
/* Store values (odd lines) in values vector */
values.push(line.unwrap());
}
}
println!("number of labels: {}", labels.len());
println!("number of values: {}", values.len());
/* Zip labels and values into one iterator */
let double_iter = labels.iter().zip(values.iter());
/* insert (label: value) pairs into hashmap */
let mut records: HashMap<&String, &String> = HashMap::new();
for (label, value) in double_iter {
records.insert(label, value);
}
}
I would like ask how to achieve this result without going though an intermediary step with vectors ?
You can use .tuples() from the itertools crate:
use itertools::Itertools;
use std::io::{stdin, BufRead};
fn main() {
for (label, value) in stdin().lock().lines().tuples() {
println!("{}: {}", label.unwrap(), value.unwrap());
}
}
See also:
This answer on "Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?"
You can manually advance an iterator with .next()
use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
fn main() {
let stdin = io::stdin();
let mut lines = stdin.lock().lines();
let mut records = HashMap::new();
while let Some(label) = lines.next() {
let value = lines.next().expect("No value for label");
records.insert(label.unwrap(), value.unwrap());
}
}
Playground
How about:
fn main() {
let lines = vec![1,2,3,4,5,6];
let mut records = std::collections::HashMap::new();
for i in (0..lines.len()).step_by(2) {
// make sure the `i+1` is existed
println!("{}{}", lines[i], lines[i + 1]);
records.insert(lines[i], lines[i + 1]);
}
}
I'm trying to get a String from standard input:
use std::io;
fn ask_nick() -> String {
let reader = io::stdin();
let mut buffer: String = String::new();
let nickname: String = reader.read_line(&mut buffer).ok()
.expect("ERRMSG").to_string();
println!("OK: Hello {}!", &nickname);
return nickname;
}
}
fn main() {
let nickname: String = ask_nick();
println!("{}", nickname);
}
But conversion from usize to String seems to change contents to it's length:
INPUT:= John
EXPECTED OUTPUT:= OK: Hello John!
John
OUTPUT:= OK: Hello 5!
5
INPUT:= Doe
EXPECTED OUTPUT:= OK: Hello Doe!
Doe
OUTPUT:= OK: Hello 4!
4
Please see the documentation, and you can see that read_line mutates the contents of its parameter (in your case, the empty string bound at buffer), putting the value read into it, and returns the length read. But you're unwrapping that result and converting that length to a string.
Instead, your function should look like:
fn ask_nick() -> String {
let reader = io::stdin();
let mut buffer: String = String::new();
reader.read_line(&mut buffer)
.ok()
.expect("ERRMSG");
println!("OK: Hello {}!", buffer);
return buffer;
}
Or, even more idiomatically, not panicking when invalid input is provided:
fn ask_nick() -> Result<String> {
let reader = io::stdin();
let mut buffer: String = String::new();
match reader.read_line(&mut buffer) {
Ok(_) => Ok(buffer),
Err(e) => Err(e),
}
}
In this variant, the caller is the one that decides how to handle errors.