Rust Read_line 'expected struct string, found f64' - rust

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.

Related

How do I take a string, convert it to an array, and then call specific characters from that array to create a new string?

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.

User input always true using the .is_ok functions

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

cannot add 1 to an unsigned integer made by construct_uint

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)

Why does a truncated string Rust print as an empty pair of parenthesis?

I have
use std::io;
fn main() {
println!("CHAR COUNT");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect(
"Failed to read line",
);
let string_length = guess.len() - 2;
let correct_string_length = guess.truncate(string_length);
println!("Your text: {}", guess);
println!("Your texts wrong length is: {}", string_length);
println!("Your texts correct length: {}", correct_string_length);
}
The last line gives me
error[E0277]: the trait bound `(): std::fmt::Display` is not satisfied
--> src/main.rs:15:47
|
15 | println!("Your texts correct length: {}", correct_string_length);
| ^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: required by `std::fmt::Display::fmt`
What am I doing wrong? If I use {:?} then I get () instead of a formatted string.
When in doubt, go to the docs - here's the function signature of String::truncate:
fn truncate(&mut self, new_len: usize)
Note two things:
It takes self as &mut.
It has no return value.
From that, the problem becomes pretty clear - truncate does not return a new truncated string, it truncates the existing string in place.
This might seem a little unintuitive at first, but Rust APIs tend not to allocate new objects in memory unless you specifically ask them to - if you're never going to use guess again, then it'd be ineffecient to create a whole new String. If you wanted to make a truncated copy, then you'd need to be explicit:
let truncated = guess.clone();
truncated.truncate(string_length);
Or if you just wanted to reference part of the existing string, you could do what Ryan's answer suggests.
Just to compliment the other answers here..
Attempting to truncate a string in Rust that is not on a character boundary will cause a runtime panic.
So while this works now:
let correct_string_length = &guess[..string_length];
If you're trying to truncate a string with wider characters, your code will panic at runtime. This is especially true if you're truncating user input.. who knows what it could be. For example:
fn main() {
let s = "Hello, 世界";
println!("{}", &s[..8]); // <--- panic
}
You can use the str::is_char_boundary(usize) method to make sure you're not about to break up a wide character accidentally:
fn print_safely(s: &str, mut idx: usize) {
loop {
if s.is_char_boundary(idx) || idx >= s.len() - 1 {
break;
}
idx += 1;
}
println!("{}", &s[..idx]);
}
User input could be anything so this is just something to consider.
Playground link: http://play.integer32.com/?gist=632ff6c81c56f9ba52e0837ff25939bc&version=stable
truncate operates in place, which is why it returns (). Looks like you’re just looking for a regular non-mutating substring:
let correct_string_length = &guess[..string_length];

Using a `let` binding to increase a values lifetime

I wrote the following code to read an array of integers from stdin:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let xs: Vec<i32> = line.unwrap()
.trim()
.split(' ')
.map(|s| s.parse().unwrap())
.collect();
println!("{:?}", xs);
}
}
This worked fine, however, I felt the let xs line was a bit long, so I split it into two:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let ss = line.unwrap().trim().split(' ');
let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();
println!("{:?}", xs);
}
}
This didn't work! Rust replied with the following error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:18
|
6 | let ss = line.unwrap().trim().split(' ');
| ^^^^^^^^^^^^^ - temporary value dropped here while still borrowed
| |
| temporary value does not live long enough
...
10 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
This confuses me. Is it line or ss that doesn't live long enough? And how can I use a let binding to increase their lifetime? I thought I was already using a let?
I've read through the lifetime guide, but I still can't quite figure it out. Can anyone give me a hint?
In your second version, the type of ss is Split<'a, char>. The lifetime parameter in the type tells us that the object contains a reference. In order for the assignment to be valid, the reference must point to an object that exists after that statement. However, unwrap() consumes line; in other words, it moves Ok variant's data out of the Result object. Therefore, the reference doesn't point inside the original line, but rather on a temporary object.
In your first version, you consume the temporary by the end of the long expression, though the call to map. To fix your second version, you need to bind the result of unwrap() to keep the value living long enough:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line.unwrap();
let ss = line.trim().split(' ');
let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();
println!("{:?}", xs);
}
}
It's about the unwrap() call, it's getting the contained object but this reference should outlive the container object, which goes out of scope in the next line (there is no local binding to it).
If you want to get cleaner code, a very common way to write it is:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let xs: Vec<i32> = line.unwrap()
.trim()
.split(' ')
.map(|s| s.parse().unwrap())
.collect();
println!("{:?}", xs);
}
}
If not, you can create the binding to the "unwrapped" result and use it.

Resources