summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Guschin <guschin.drew@gmail.com>2023-02-16 21:43:45 +0400
committerAndrew Guschin <guschin.drew@gmail.com>2023-02-16 21:43:45 +0400
commitad8ba9184d4c3b6eff9d251a8677853075975fce (patch)
treed75028f9033cd9434abd5211c886c2b8d6cf7f65
parentb57d081d9bcbe15870ba6d9cf98bb38f188e63ee (diff)
Добавлена поддержка недесятичных систем счисления и обработка ошибок
-rw-r--r--sem2/src/main.rs44
-rw-r--r--sem2/src/mpn.rs40
2 files changed, 70 insertions, 14 deletions
diff --git a/sem2/src/main.rs b/sem2/src/main.rs
index f60350d..ed33b43 100644
--- a/sem2/src/main.rs
+++ b/sem2/src/main.rs
@@ -2,10 +2,42 @@ use inquire::Text;
mod mpn;
fn main() {
- let a = Text::new("Введите число:").prompt().unwrap();
- let a = mpn::Number::parse(&a).unwrap();
- let b = Text::new("Введите число:").prompt().unwrap();
- let b = mpn::Number::parse(&b).unwrap();
- let c = a + b;
- println!("Number: {}", c);
+ let radix = match Text::new("Введите основание системы счисления:").prompt()
+ {
+ Ok(text) => text,
+ Err(_) => return,
+ };
+ let radix = match radix.parse::<usize>() {
+ Ok(number) => number,
+ Err(_) => {
+ println!("Основание должно быть десятичным числом");
+ return;
+ }
+ };
+
+ let a = match Text::new("Введите число:").prompt() {
+ Ok(text) => text,
+ Err(_) => return,
+ };
+ let a = match mpn::Number::parse(&a, radix) {
+ Ok(number) => number,
+ Err(what) => {
+ println!("{what}");
+ return;
+ }
+ };
+
+ let b = match Text::new("Введите число:").prompt() {
+ Ok(text) => text,
+ Err(_) => return,
+ };
+ let b = match mpn::Number::parse(&b, radix) {
+ Ok(number) => number,
+ Err(what) => {
+ println!("{what}");
+ return;
+ }
+ };
+
+ println!("Сумма: {}", a + b);
}
diff --git a/sem2/src/mpn.rs b/sem2/src/mpn.rs
index 27f94e0..ecc1d5c 100644
--- a/sem2/src/mpn.rs
+++ b/sem2/src/mpn.rs
@@ -8,16 +8,21 @@ pub struct Number {
}
impl Number {
- pub fn parse(snum: &str) -> Result<Number, &str> {
- let radix = 10_usize;
+ pub fn parse(snum: &str, radix: usize) -> Result<Number, &str> {
let snum = snum.as_bytes();
let mut digits = Vec::new();
for i in (0..snum.len()).rev() {
- let digit = snum[i] - '0' as u8;
- if digit as usize >= radix {
- return Err("Аргумент не является числом");
- } else {
- digits.push(digit);
+ match Number::parse_digit(snum[i]) {
+ Some(digit) => {
+ if digit as usize >= radix {
+ return Err("Аргумент не является числом");
+ } else {
+ digits.push(digit);
+ }
+ }
+ None => {
+ return Err("Аргумент не является числом");
+ }
}
}
return Ok(Number { radix, digits });
@@ -26,12 +31,31 @@ impl Number {
pub fn len(&self) -> usize {
self.digits.len()
}
+
+ fn parse_digit(c: u8) -> Option<u8> {
+ if c >= 'a' as u8 {
+ Some(c - 'a' as u8 + 10_u8)
+ } else if c >= '0' as u8 {
+ Some(c - '0' as u8)
+ } else {
+ None
+ }
+ }
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for i in (0..self.digits.len()).rev() {
- write!(f, "{}", self.digits[i])?;
+ let digit = if self.digits[i] > 9 {
+ ('a' as u8 - 10 + self.digits[i]) as char
+ } else {
+ ('0' as u8 + self.digits[i]) as char
+ };
+ write!(f, "{}", digit)?;
+ }
+
+ if self.radix != 10 {
+ write!(f, "_{}", self.radix)?;
}
return Ok(());
}