Issue with parsing String to Unsigned in Rust language - parsing

This is the code I have:
fn main() {
use std::io::stdin;
let mut s=String::new();
stdin().read_line(&mut s).expect("Wrong input");
let n = s.parse::<u32>();
println!("Try: {:?}", n);
}
I get no error while compiling, but it prints this in running time:
Err(ParseIntError { kind: InvalidDigit })

You have a trailing \n in your string, use String::trim_end:
fn main() {
let n = "10\n".trim_end().parse::<u32>();
println!("Try: {:?}", n);
}
From BufRead::read_line documentation:
This function will read bytes from the underlying stream until the
newline delimiter (the 0xA byte) or EOF is found. Once found, all
bytes up to, and including, the delimiter (if found) will be appended
to buf.

Related

Parsing an f64 variable into a usize variable in Rust

I have currently been dabbling in the Rust programming language and decided a good way to test my skills was to program an application that would find the median of any given list of numbers.
Eventually I got into the Final stretch of code and stumbled into a problem.
I needed to parse an f64 variable into a usize variable.
However, I don't know how to go about doing this (Wow what a surprise!).
Take a look at the second function, calc_med() in my code. The variable n2 is supposed to take n and parse it into a usize. The code is not finished yet, but if you can see any more problems with the code please let me know.
use std::io;
use std::sync::Mutex;
#[macro_use]
extern crate lazy_static;
lazy_static! {
static ref v1: Mutex<Vec<f64>> = Mutex::new(Vec::new());
}
fn main() {
loop {
println!("Enter: ");
let mut inp: String = String::new();
io::stdin().read_line(&mut inp).expect("Failure");
let upd_inp: f64 = match inp.trim().parse() {
Ok(num) => num,
Err(_) => if inp.trim() == String::from("q") {
break;
} else if inp.trim() == String::from("d"){
break
{
println!("Done!");
calc_med();
}
} else {
continue;
}
};
v1.lock().unwrap().push(upd_inp);
v1.lock().unwrap().sort_by(|a, b| a.partial_cmp(b).unwrap());
println!("{:?}", v1.lock().unwrap());
}
}
fn calc_med() { // FOR STACKOVERFLOW: THIS FUNCTION
let n: f64 = ((v1.lock().unwrap().len()) as f64 + 1.0) / 2.0;
let n2: usize = n.to_usize().expect("Failure");
let median: f64 = v1[n2];
println!("{}", median)
}

How to typecast fixed size byte array as struct?

I want to reinterpret a stack allocated byte array as a stack allocated (statically guaranteed) struct without doing any work - just to tell the compiler that "Yes, I promise they are the same size and anything". How do I do that?
I tried transmute, but it doesn't compile.
fn from_u8_fixed_size_array<T>(arr: [u8; size_of::<T>()]) -> T {
unsafe { mem::transmute(arr) }
}
cannot transmute between types of different sizes, or dependently-sized types E0512
Note: source type: `[u8; _]` (this type does not have a fixed size)
Note: target type: `T` (this type does not have a fixed size)
There is also this variant of such a function, that compiles, but it requires T to be Copy:
fn from_u8_fixed_size_array(arr: [u8; size_of::<T>()]) -> T {
unsafe { *(&arr as *const [u8; size_of::<T>()] as *const T) }
}
With Rust 1.64 I have a compilation error on [u8; size_of::<T>()] (cannot perform const operation using T).
I tried with a const generic parameter but the problem is still the same (I cannot introduce a where clause to constrain this constant to match size_of::<T>()).
Since the array is passed by value and the result is a value, some bytes have to be copied ; this implies a kind of memcpy().
I suggest using a slice instead of an array and checking the size at runtime.
If you are ready to deal with undefined behaviour, you might consider the second version which does not copy anything: it just reinterprets the storage as is.
I'm not certain I would do that, however...
Edit
The original code was compiled with nightly and a specific feature.
We can simply use transmute_copy() to get the array by value and emit a value.
And, I think the functions themselves should be qualified with unsafe instead of just some of their operations, because nothing guaranties (statically) that these conversions are correct.
#![feature(generic_const_exprs)] // nightly required
unsafe fn from_u8_slice_v1<T>(arr: &[u8]) -> T {
let mut result = std::mem::MaybeUninit::<T>::uninit();
let src = &arr[0] as *const u8;
let dst = result.as_mut_ptr() as *mut u8;
let count = std::mem::size_of::<T>();
assert_eq!(count, arr.len());
std::ptr::copy_nonoverlapping(src, dst, count);
result.assume_init()
}
unsafe fn from_u8_slice_v2<T>(arr: &[u8]) -> &T {
let size = std::mem::size_of::<T>();
let align = std::mem::align_of::<T>();
assert_eq!(size, arr.len());
let addr = &arr[0] as *const _ as usize;
assert_eq!(addr % align, 0);
&*(addr as *const T) // probably UB
}
unsafe fn from_u8_fixed_size_array<T>(
arr: [u8; std::mem::size_of::<T>()]
) -> T {
std::mem::transmute_copy(&arr)
}
fn main() {
let a = [1, 2];
println!("{:?}", a);
let i1 = unsafe { from_u8_slice_v1::<i16>(&a) };
println!("{:?}", i1);
let i2 = unsafe { from_u8_slice_v2::<i16>(&a) };
println!("{:?}", i2);
let i3 = unsafe { from_u8_fixed_size_array::<i16>(a) };
println!("{:?}", i3);
}
/*
[1, 2]
513
513
513
*/

How to parse an octal string as a float in Rust?

I need to take an octal string, such as "42.1", and get a float from it (34.125). What's the best way to do this in Rust? I see there previously was a from_str_radix function, but it's now removed.
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseFloatError {
_private: (),
}
impl ParseFloatError {
fn new() -> ParseFloatError {
ParseFloatError { _private: () }
}
}
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Could not parse float")
}
}
pub fn parse_float_radix(s: &str, radix: u32) -> Result<f64, ParseFloatError> {
let s2 = s.replace(".", "");
let i = i64::from_str_radix(&s2, radix).map_err(|_| ParseFloatError::new())?;
let count = s.split('.').count();
let fraction_len: usize;
match count {
0 => unreachable!(),
1 => fraction_len = 0,
2 => fraction_len = s.split('.').last().unwrap().len(),
_ => return Err(ParseFloatError::new()),
}
let f = (i as f64) / f64::from(radix).powi(fraction_len as i32);
Ok(f)
}
fn main() {
println!("{}", parse_float_radix("42.1", 8).unwrap());
}
It first parses the input as an integer and then divides it by radix^number_of_fractional_digits.
It doesn't support scientific notation or special values like infinity or NaN. It also fails if the intermediate integer overflows.
Since posting this question, a crate has appeared that solves this: lexical. Compiling with the radix feature enables a parse_radix function, which can parse strings into floats with radices from 2 to 36.

Swift 3 - How to convert memory of Int32 as four characters

I want to convert an Int32 to a string consisting of four C-style, 1-byte wide characters (probably closely related to this but in Swift 3).
The use for this is that many API functions of Core Audio return an OSStatus (really an Int32), which can often be interpreted as string consisting of four C-style characters.
fun interpretAsString(possibleMsg: Int32) -> String {
// Blackbox
}
Actually a "four character code" is usually an unsigned 32-bit
value:
public typealias FourCharCode = UInt32
public typealias OSType = FourCharCode
The four bytes (from the MSB to the LSB) each define one character.
Here is a simple Swift 3 function to convert the integer to a string,
inspired by the various C/Objective-C/Swift 1+2 solutions in
iOS/C: Convert "integer" into four character string:
func fourCCToString(_ value: FourCharCode) -> String {
let utf16 = [
UInt16((value >> 24) & 0xFF),
UInt16((value >> 16) & 0xFF),
UInt16((value >> 8) & 0xFF),
UInt16((value & 0xFF)) ]
return String(utf16CodeUnits: utf16, count: 4)
}
Example:
print(fourCCToString(0x48454C4F)) // HELO
I have chosen an array with the UTF-16 code points as intermediate storage because that can directly be used to create a string.
If you really need it for a signed 32-bit integer then you can
call
fourCCToString(FourCharCode(bitPattern: i32value)
or define a similar function taking an Int32 parameter.
As Tim Vermeulen suggested below, the UTF-16 array can also be
created with map:
let utf16 = stride(from: 24, through: 0, by: -8).map {
UInt16((value >> $0) & 0xFF)
}
or
let utf16 = [24, 16, 8, 0].map { UInt16((value >> $0) & 0xFF) }
Unless the function is performance critical for your application,
pick what you feel most familiar with (otherwise measure and compare).
I don't test this code but try this:
func interpretAsString(possibleMsg: Int32) -> String {
var result = String()
result.append(Character(UnicodeScalar(UInt32(possibleMsg>>24))!))
result.append(Character(UnicodeScalar(UInt32((possibleMsg>>16) & UInt32(0xFF)))!))
result.append(Character(UnicodeScalar(UInt32((possibleMsg>>8) & UInt32(0xFF)))!))
result.append(Character(UnicodeScalar(UInt32((possibleMsg) & UInt32(0xFF)))!))
return result
}
This may be an old question, but since it was asking in the context of Core Audio, I just wanted to share a variant I was playing with.
For Core Audio, where some (but not all?) OSStatus/Int32 values are defined using four characters, some code from Apple's old Core Audio Utility Classes can provide inspiration (very similar to the linked question)
From CAXException.h:
class CAX4CCStringNoQuote {
public:
CAX4CCStringNoQuote(OSStatus error) {
// see if it appears to be a 4-char-code
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str, &beErr, 4);
if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
str[4] = '\0';
} else if (error > -200000 && error < 200000)
// no, format it as an integer
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
In Swift 5, one rough translation (without the hex representation for large values) might be:
private func osStatusToString(_ value: OSStatus) -> String {
let data = withUnsafeBytes(of: value.bigEndian, { Data($0) })
// If all bytes are printable characters, we treat it like characters of a string
if data.allSatisfy({ 0x20 <= $0 && $0 <= 0x7e }) {
return String(data: data, encoding: .ascii)!
} else {
return String(value)
}
}
Note that the Data initializer is making a copy of the bytes, though it may be possible to avoid that if desired.
Of course, with Core Audio we encounter four character codes with both Int32 and UInt32 types. I haven't done generics with Swift before, but one way to handle them in a single function could be:
private func stringifyErrorCode<T: FixedWidthInteger>(_ value: T) -> String {
let data = withUnsafeBytes(of: value.bigEndian, { Data($0) })
// If all bytes are printable characters, we treat it like characters of a string
if data.allSatisfy({ 0x20 <= $0 && $0 <= 0x7e }) {
return String(data: data, encoding: .ascii)!
} else {
return String(value, radix: 10)
}
}
This may not be suitable for general purpose handling of four character codes (I've seen other answers that support characters in the MacOS Roman encoding versus ASCII in the example above. There's likely some history there I'm not aware of), but may be reasonable for Core Audio status/selector codes.

Parsing strings into integers

So I'm trying to find a pattern in a string and convert it to an integer.
Firstly I look for a string:
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let http_location = haystack.rfind(needle);
if (http_location.is_some()) {
Now that I've found it I can think of two ways to get the numerical status. Either:
let mut temp_str = haystack.char_at(http_location.unwrap());
let status = String::from_str(temp_str);
}
Or:
let status = String::from_str(&haystack[http_location.unwrap()]);
}
Unfortunately both of them are deprecated (and probably wrong anyway). What is currently the correct way of doing this?
Also, is this part stylistically correct?:
let http_location = haystack.rfind(needle);
if (http_location.is_some())
Parsing is a wide and varied topic. There are easy parsing tools and there are performant parsing tools and a spectrum in between.
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let z: Option<u8> = haystack.rfind(needle).and_then(|pt| {
let after_match = &haystack[(pt + needle.len())..];
after_match.splitn(2, " ").next()
}).and_then(|val| {
val.parse().ok()
});
println!("{:?}", z)
}
Here, we use rfind as you did before, which can fail. We use and_then to run the closure if the result was Some. The first closure slices the string after the needle, then splits it on spaces, with a maximum of 2 parts. That can fail, so we use a second and_then to use parse, which can also fail with a Result, so we convert that into an Option to preserve the type.
And the end of this, we still might have failed, as the thing we parsed might not have been a parseable number!
Rust really helps you make explicit places you can fail, and you have to deal with them. ^_^
In this case:
Maybe the string doesn't have "HTTP/1." in it
Iterators have to end at some point, so they can return None.
Parsing a string to a number can fail.
Here's an alternate solution that uses the regex crate:
extern crate regex;
use regex::Regex;
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let re = Regex::new(r"HTTP/1.(\d) (\d+)\r\n").unwrap();
let captures = re.captures(haystack).unwrap();
let version: Option<u8> = captures.at(1).and_then(|version| version.parse().ok());
let status: Option<u8> = captures.at(2).and_then(|version| version.parse().ok());
assert_eq!(Some(1), version);
assert_eq!(Some(200), status);
println!("Version: {:?}, Status: {:?}", version, status);
}
You'll see that we have the same types of failure modes, but the structure is a bit different.
Or maybe a version that uses Result and try!:
#[derive(Debug,Copy,Clone,PartialEq)]
enum Error {
StartNotFound,
NotANumber,
}
fn parse_it(haystack: &str) -> Result<u8, Error> {
let needle = "HTTP/1.";
let pt = try!(haystack.rfind(needle).ok_or(Error::StartNotFound));
let after_match = &haystack[(pt + needle.len())..];
let val = after_match.splitn(2, " ").next().unwrap();
val.parse().map_err(|_| Error::NotANumber)
}
fn main() {
println!("{:?}", parse_it("HTTP/1.1 200\r\n"));
println!("{:?}", parse_it("HTTP/1"));
println!("{:?}", parse_it("HTTP/1.cow"));
}

Resources