How can I read from the console and avoid crashing if the user presses enter without entering anything?
let mut objectnumber = String::new();
println!("mennyi súlyt szeretnél megnézni? 3.=255 int");
if io::stdin().read_line(&mut objectnumber).is_ok() {
println!("{}csdcds", objectnumber);
}
//panic!("{}",objectnumber.len());
if objectnumber.len() < 3 {
let localrandnum: u8 = thread_rng().gen_range(0..=255);
println!("miután nem adtál meg semmit sem ezért {localrandnum}.at írtam be neked");
objectnumber = localrandnum.to_string();
}
let objectnumber: u8 = objectnumber.trim().parse::<u8>().expect("null");
This is working but I don't think it should be done like this in Rust.
I don't know why is it ok even on empty line while the parse is talking about it being empty.
Fixes I made:
read_line returns a Result indicating whether or not there was an error reading from stdin. Usually this only happens in very specific circumstances, so let's just unwrap this for now.
objectnumber.len() gives you the length of the string, not its content. To check its content for < 3, we need to parse() it to a u8 first.
Don't expect the parse, because this one depends on user input. Do a proper error handling instead. This is the point that will tell you if the number is >255, <0 or something else entirely. Let's for now just default to '0', because it will then get caught by the < 3.
Don't convert the number you generated with the thread_rng to a String; instead, write it to objectnumber directly. There is no point in converting it to a String and back.
use std::io;
use rand::{thread_rng, Rng};
fn main() {
let mut objectnumber = String::new();
println!("mennyi súlyt szeretnél megnézni? 3.=255 int");
io::stdin()
.read_line(&mut objectnumber)
.expect("Unable to read from stdin!");
// Convert from String to u8
let mut objectnumber: u8 = objectnumber.trim().parse::<u8>().unwrap_or(0);
if objectnumber < 3 {
objectnumber = thread_rng().gen_range(0..=255);
println!("miután nem adtál meg semmit sem ezért {objectnumber}.at írtam be neked");
}
println!("objectnumber: {}", objectnumber);
}
mennyi súlyt szeretnél megnézni? 3.=255 int
33
objectnumber: 33
mennyi súlyt szeretnél megnézni? 3.=255 int
1
miután nem adtál meg semmit sem ezért 191.at írtam be neked
objectnumber: 191
Related
Now that I'm typing it, this seems like a very convoluted process that could definitely be solved easier. Ignoring that for the moment, I'm trying to take a string (from user input), separate the characters into an array, then call individual characters to make a new string. The issue I'm running into is that the "join" function doesn't like working with the "Vec" function (not sure if function is the right term, sorry). Here is my code so far:
use std::io;
fn main() {
println!("Enter P1:");
let mut mono = String::new();
io::stdin()
.read_line(&mut mono)
.expect("Failed to read line");
let mono: Vec<char> = mono.chars().collect();
let x = [mono[0],mono[1]].join("");
println!("Square 1: {x}");
}
I'm very new to Rust, so any suggestions are extremely helpful. Thank you!
You could always just slice the original string str[a..b].to_string().
If you need to work with char arrays, there's String::from_iter and collecting into a String. Example:
fn main() {
let string = "My String".to_string();
let substr1 = string[0..3].to_string();
let substr2 = string[3..].to_string();
println!("substr1 = {}", substr1);
println!("substr2 = {}", substr2);
let chars: Vec<_> = string.chars().collect();
let collected_substr1: String = chars.iter().take(2).collect();
let collected_substr2: String = chars.iter().skip(3).collect();
println!("collected_substr1 = {}", collected_substr1);
println!("collected_substr2 = {}", collected_substr2);
let from_iter_substr1 = String::from_iter([chars[0], chars[1]].iter());
let from_iter_substr2 = String::from_iter(chars.iter().skip(3));
println!("from_iter_substr1 = {}", from_iter_substr1);
println!("from_iter_substr2 = {}", from_iter_substr2);
}
Vec is a type, FYI.
join only works on string slices (&str), not chars. Assuming you are just trying to join two characters without a separator, you can do
let x: String = mono.chars().take(2).collect();
If the goal is only to extract a substring from the input it can be done much simpler
use std::io;
fn main() {
println!("Enter P1:");
let mut mono = String::new();
io::stdin()
.read_line(&mut mono)
.expect("Failed to read line");
let x = &mono[..2].to_string(); // get rhe slice you need and create a new string from it
println!("Square 1: {x}");
}
Edit
As pointed out in comments, note that in a real life use case you should check the length of your string before slicing in it with arbitrary indexes... this example could easily crash at runtime.
I'm new in rust and stuck in the error below, and i could not find any clue on it. Anyone can point me out? I got no idea how to define the read_line in float.
.read_line(&mut fahrenheit)
| ^^^^^^^^^^^^^^^ expected struct String, found f64
fn main(){
println!("enter fahrenheit: ");
//io::stdin() .read_line(&mut index) .expect("Failed to read line");
let mut fahrenheit: f64 = 66.66;
io::stdin()
.read_line(&mut fahrenheit)
.expect("fail to read");
let tempConvert = fahrenheitToCelsius(fahrenheit);
println!("convert from {tempConvert}");
}
fn fahrenheitToCelsius(x: f64) -> f64{
let mut gt: f64;
gt = (x - 32.00) * 5.00 / 9.00;
gt
}
read_line will read a string from stdin, and it needs a buffer to put it in, which is supposed to be argument you pass it. If, then, you want to convert it, it's your job: it won't do that on its own. Thus the type error. To achieve what you want, simply create a buffer, then parse it.
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).expect("Failed to read");
let fahrenheit = buffer.trim().parse::<f64>().expect("Failed to parse as `f64'");
Note that in your code, the generic argument of parse might be left implicit since your fahrenheitToCelsius function might be enough for the compiler to figure out the type to perform the conversion to.
So I have a code which constantly asks for input and then executes your input as a shell command. I understand that the output I am getting from the shell commands is in a buffer of some sort. Now, however, as there are many commands which output lots of lines, I would like to get all of the output into one single string.
extern crate subprocess;
use std::io;
use std::io::{BufRead, BufReader};
use subprocess::Exec;
fn main() {
loop {
let mut mycommand_string: String = String::new();
io::stdin()
.read_line(&mut mycommand_string)
.expect("Failed to read line");
let mycommand: &str = &*mycommand_string;
let x = Exec::shell(mycommand).stream_stdout().unwrap();
let br = BufReader::new(x);
let full: String = " ".to_string();
let string = for (i, line) in br.lines().enumerate() {
let string: String = line.unwrap().to_string();
let full = format!("{}{}", full, string);
println!("{}", full);
};
println!("{}", string);
}
}
This is my code. As you can see, the thing I am aiming for is to somehow iterate over br.lines() and for each line of output it contains, append or concatenate it to a string, so that all the output ends up in one single string, preferably with "\n" in between each line, but not neccesarilly.
Specifically I would like to iterate over the result of the variable br which has a type I dont understand and to concatenate all the strings together.
If you have an iterator of lines, then you can simply collect that into a string:
br.lines().collect();
Of course we should not ignore that there do not seem to be many possible reasons for ever doing that...
I was doing the adventofcode of 2020 day 3 in Rust to train a little bit because I am new to Rust and I my code would not compile depending if I used single quotes or double quotes on my "tree" variable
the first code snippet would not compile and throw the error: expected u8, found &[u8; 1]
use std::fs;
fn main() {
let text: String = fs::read_to_string("./data/text").unwrap();
let vec: Vec<&str> = text.lines().collect();
let vec_vertical_len = vec.len();
let vec_horizontal_len = vec[0].len();
let mut i_pointer: usize = 0;
let mut j_pointer: usize = 0;
let mut tree_counter: usize = 0;
let tree = b"#";
loop {
i_pointer += 3;
j_pointer += 1;
if j_pointer >= vec_vertical_len {
break;
}
let i_index = i_pointer % vec_horizontal_len;
let character = vec[j_pointer].as_bytes()[i_index];
if character == tree {
tree_counter += 1
}
}
println!("{}", tree_counter);
}
the second snippet compiles and gives the right answer..
use std::fs;
fn main() {
let text: String = fs::read_to_string("./data/text").unwrap();
let vec: Vec<&str> = text.lines().collect();
let vec_vertical_len = vec.len();
let vec_horizontal_len = vec[0].len();
let mut i_pointer: usize = 0;
let mut j_pointer: usize = 0;
let mut tree_counter: usize = 0;
let tree = b'#';
loop {
i_pointer += 3;
j_pointer += 1;
if j_pointer >= vec_vertical_len {
break;
}
let i_index = i_pointer % vec_horizontal_len;
let character = vec[j_pointer].as_bytes()[i_index];
if character == tree {
tree_counter += 1
}
}
println!("{}", tree_counter);
}
I did not find any reference explaining what is going on when using single or double quotes..can someone help me?
The short answer is it works similarly to java. Single quotes for characters and double quotes for strings.
let a: char = 'k';
let b: &'static str = "k";
The b'' or b"" prefix means take what I have here and interpret as byte literals instead.
let a: u8 = b'k';
let b: &'static [u8; 1] = b"k";
The reason strings result in references is due to how they are stored in the compiled binary. It would be too inefficient to store a string constant inside each method, so strings get put at the beginning of the binary in header area. When your program is being executed, you are taking a reference to the bytes in that header (hence the static lifetime).
Going further down the rabbit hole, single quotes technically hold a codepoint. This is essentially what you might think of as a character. So a Unicode character would also be considered a single codepoint even though it may be multiple bytes long. A codepoint is assumed to fit into a u32 or less so you can safely convert any char by using as u32, but not the other way around since not all u32 values will match valid codepoints. This also means b'\u{x}' is not valid since \u{x} may produce characters that will not fit within a single byte.
// U+1F600 is a unicode smiley face
let a: char = '\u{1F600}';
assert_eq!(a as u32, 0x1F600);
However, you might find it interesting to know that since Rust strings are stored as UTF-8, codepoints over 127 will occupy multiple bytes in a string despite fitting into a single byte on their own. As you may already know, UTF-8 is simply a way of converting codepoints to bytes and back again.
let foo: &'static str = "\u{1F600}";
let foo_chars: Vec<char> = foo.chars().collect();
let foo_bytes: Vec<u8> = foo.bytes().collect();
assert_eq!(foo_chars.len(), 1);
assert_eq!(foo_bytes.len(), 4);
assert_eq!(foo_chars[0] as u32, 0x1F600);
assert_eq!(foo_bytes, vec![240, 159, 152, 128]);
I am trying to write a program that calculates the n^n! of any given positive integer in rust, I am using the uint crate to manage the very big numbers that I will be dealing with. However, I have accomplished everything I need, except, when I try to add 1 to the integer I made as 1024 bits, it does not allow this however, as it says that they are mismatched types. How can I make it so that I can do this. I am also welcome to other suggestions as to how to do this. Thank you, kind stranger for helping me.
The code of "main.rs"
use std::io;
use uint::construct_uint;
fn main() {
construct_uint! {
pub struct U1024(16);
};
let mut factorial: U1024;
println!("What is n?");
let mut number = String::new();
io::stdin().read_line(&mut number)
.expect("Failed to read line");
let n = number.parse::<i32>().unwrap();
for i in 1..n+1 {
// This is the bit that makes it not compile
let mut x: U1024;
x += 1;
factorial = factorial * x
}
let mut result: U1024;
result = factorial * factorial;
println!("n^n! is {}", result);
}
P.S. (My full code can be found here: https://github.com/pigeon-king-17/ntonfactorial)