This question already has answers here:
Why does my string not match when reading user input from stdin?
(3 answers)
Closed 4 years ago.
In an exercise to learn Rust, I'm trying a simple program that will accept your name, then print your name if it's Valid.
Only "Alice" and "Bob" are valid names.
use std::io;
fn main() {
println!("What's your name?");
let mut name = String::new();
io::stdin().read_line(&mut name)
.ok()
.expect("Failed to read line");
greet(&name);
}
fn greet(name: &str) {
match name {
"Alice" => println!("Your name is Alice"),
"Bob" => println!("Your name is Bob"),
_ => println!("Invalid name: {}", name),
}
}
When I cargo run this main.rs file, I get:
What's your name?
Alice
Invalid name: Alice
Now, my guess is, because "Alice" is of type &'static str and name is of type &str, maybe it's not matching correctly...
I bet that it isn't caused by type mismatch. I place my bet on that there are some invisible characters (new line in this case). To achieve your goal you should trim your input string:
match name.trim() {
"Alice" => println!("Your name is Alice"),
"Bob" => println!("Your name is Bob"),
_ => println!("Invalid name: {}", name),
}
Related
I have a error on the first parsing: may panic if the index is out of bounds.
But the if before parsing shoud handle this.
How to handle the error correctly?
print!("Write 2 ints separated by space: ");
let mut nums_string: String = String::new();
stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
stdin()
.read_line(&mut nums_string)
.expect(ERR_MSG_STDIN_READ_LINE);
let nums_str_vec: Vec<&str> = nums_string.trim().split(' ').collect();
let num1: i32;
let num2: i32;
if nums_str_vec.len() == 2 {
num1 = match nums_str_vec[0].parse() {
Err(_) => panic!("Wrong input"),
Ok(_) => nums_str_vec[0].parse().unwrap(),
};
num2 = match nums_str_vec[1].parse() {
Err(_) => panic!("Wrong input"),
Ok(_) => nums_str_vec[1].parse().unwrap(),
};
} else {
panic!("Wrong input");
}
Is possible to handle error without if and use only the match?
The solution for handling "may panic" if you know it won't panic is to not repeat the code that may panic.
If you have already determined that it is a number by matching the Ok case, you do not need to parse it again.
The number is contained in the Ok value, which you currently ignore. Use it!
Ok(n) => n,
Is possible to handle error without if and use only the match?
Complemeting mkrieger1's answer, a few additional transformations before the vec will give you a much simpler match thanks to slice patterns:
let nums: Vec<Result<i32, _>> = nums_string.trim().split_whitespace().map(str::parse).collect();
match nums[..] {
[Ok(n1), Ok(n2)] => println!("{} {}", n1, n2),
_ => println!("Wrong input"),
}
NOTE: I'm totally Newbie in Standard ML. I merely have basic F# knowledge.
This is a good ol' code in C
#include <stdio.h>
int main()
{
char str[100]; // size whatever you want
scanf("%s", str);
printf("%s\n", str);
return 0;
}
now, I want to make a Standard ML-version-equivalent of this code. so I tried this:
val str = valOf (TextIO.inputLine TextIO.stdIn)
val _ = print str
but my SML/NJ says this:
uncaught exception Option
raised at: smlnj/init/pre-perv.sml:21.28-21.34
I googled it, and I also searched this site, but I cannot find any solution which doesn't cause error.
does anyone knows it?
EDIT: I tried this code:
fun main =
let val str = valOf (TextIO.inputLine TextIO.stdIn)
in
case str
of NONE => print "NONE\n"
| _ => print str
end
but it also makes error:
stdIn:1.6-1.10 Error: can't find function arguments in clause
stdIn:4.9-6.33 Error: case object and rules don't agree [tycon mismatch]
rule domain: 'Z option
object: string
in expression:
(case str
of NONE => print "NONE\n"
| _ => print str)
This answer was pretty much given in the next-most recent question tagged sml: How to read string from user keyboard in SML language? -- you can just replace the user keyboard with stdin, since stdin is how you interact with the keyboard using a terminal.
So you have two problems with this code:
fun main =
let val str = valOf (TextIO.inputLine TextIO.stdIn)
in
case str
of NONE => print "NONE\n"
| _ => print str
end
One problem is that if you write fun main then it has to take arguments, e.g. fun main () = .... The () part does not represent "nothing" but rather exactly one thing, being the unit value.
The other problem is eagerness. The Option.valOf function will crash when there is no value, and it will do this before you reach the case-of, making the case-of rather pointless. So what you can do instead is:
fun main () =
case TextIO.inputLine TextIO.stdIn of
SOME s => print s
| NONE => print "NONE\n"
Using the standard library this can be shortened to:
fun main () =
print (Option.getOpt (TextIO.inputLine TextIO.stdIn, "NONE\n"))
I encourage you to read How to read string from user keyboard in SML language?
This question already has an answer here:
Regex with replace in Golang
(1 answer)
Closed 3 years ago.
I have a file with dates in the format dd.mm.yyyy (e.g. 31.12.2019).
I want to transform into format yyyy-mm-dd (e.g. 2019-12-31).
In Notepad++ I can do a Search and Replace with these strings using back references:
Search:
(\d{2}).(\d{2}).(\d{4})
Replace:
\3-\2-\1
How would I do this with Go?
You could do it by slicing your input string, and assembling the parts in different order:
func transform(s string) string {
d, m, y := s[:2], s[3:5], s[6:]
return y + "-" + m + "-" + d
}
Note: the above function does not validate the input, it could panic if the input is shorter than 6 bytes.
If you need input validation (including date validation), you could use the time package to parse the date, and format it into your expected output:
func transform2(s string) (string, error) {
t, err := time.Parse("02.01.2006", s)
if err != nil {
return "", err
}
return t.Format("2006-01-02"), nil
}
Testing the above functions:
fmt.Println(transform("31.12.2019"))
fmt.Println(transform2("31.12.2019"))
Output (try it on the Go Playground):
2019-12-31
2019-12-31 <nil>
regex might be overkill since you have such well defined input. how about this:
var dmy = strings.Split("31.12.2019",".")
var mdy = []string{dmy[1],dmy[0],dmy[2]}
fmt.Println(strings.Join(mdy, "-"))
https://play.golang.org/p/Ak3TlCAGHUv
This question already has answers here:
How to compare a string with another where the one has space in between
(4 answers)
Closed 4 years ago.
Is there any regex to match substring if they have space in between in scala ?
For eg:
"hero 6 go pro" contains "gopro" should return true
"go pro hero 6 " contains "gopro" should return true
I tried :
def matchWords(input: Seq[Char], words: Seq[Char]): Boolean = (input, words) match {
case (Seq(), Seq() | Seq(' ', _*)) => true
case (Seq(), _) => false
case (Seq(a, tail#_*), Seq(b, rest#_*)) if a == b => matchWords(tail, rest)
case (_, Seq(' ', rest#_*)) => matchWords(input, rest)
case _ => false
}
but
matchWords("gopro", "hero 6 go pro") returns false
though this matchWords("fitbit", "fit bit versa") return true.
The string should match nouns.
Any idea what I am doing wrong here ?
Thanks,
Shalini
A user with the same "name" as you has already asked a very similar question here and been given multiple answers, including one from me.
The code in your question appears to be copied from another of those answers. Unfortunately you picked the lowest-scoring answer which doesn't give the right results.
I suggest that you try my answer from that question...
As I frequently observe and how I often implement a name attribute, is to simply model it as String.
What now, if the name has to follow a certain syntax, i.e. format? In Java I probably would define a constructor with a check on its arguments, something like:
public Name(str: String) {
if (str == null) throw new IllegalArgumentException("Str must not be null.");
if (!str.matches("name format expressed as regex")) throw new IllegalArgumentException("Str must match 'regex' but was " + str);
this.str = str;
}
In Scala I came up with the following solution:
import StdDef.Str
import StdDef.Bol
import StdDef.?
import scala.util.parsing.combinator.RegexParsers
final case class Name private (pfx: ?[Str] = None, sfx: Str) {
override def toString = pfx.mkString + sfx
}
object Name extends RegexParsers {
implicit def apply(str: Str): Name = parseAll(syntax, str) match {
case Success(res, _) => Name(res._1, res._2)
case rej: NoSuccess => error(rej.toString)
}
lazy val syntax = (prefix ?) ~! suffix
lazy val prefix = (("x" | "X") ~! hyph) ^^ { case a ~ b => a + b }
lazy val suffix = alpha ~! (alpha | digit | hyph *) ^^ { case a ~ b => a + b.mkString }
lazy val alpha: Parser[Str] = """\p{Alpha}""".r
lazy val digit: Parser[Str] = """\p{Digit}""".r
lazy val hyph: Parser[Str] = "-"
override lazy val skipWhitespace = false
}
My intents here are:
Compose a Name from its natural representation, i.e. a String value
Check whether its natural representation forms a valid Name at construction time.
Disallow any other construction than through the factory method apply:(str:Str)Str.
Make the construction from its natural representation implicit, e.g. val a: Name = "ISBN 978-0-9815316-4-9".
Decompose a Name into its parts according to its syntactical elements.
Have errors being thrown with messages, such as:
===
--
^
[1.3] error: string matching regex `\p{Alpha}' expected but end of source found
I would like to know what solutions you come up with.
After giving the topic some more thoughts, I am currently taking the following approach.
Token.scala:
abstract class Token {
val value: Str
}
object Token {
def apply[A <: Token](ctor: Str => A, syntax: Regex) = (value: Str) => value match {
case syntax() => ctor(value)
case _ => error("Value must match '" + syntax + "' but was '" + value + "'.")
}
}
Tokens.scala:
final case class Group private (val value: Str) extends Token
final case class Name private (val value: Str) extends Token
trait Tokens {
import foo.{ bar => outer }
val Group = Token(outer.Group, """(?i)[a-z0-9-]++""".r)
val Name = Token(outer.Name, """(?i)(?:x-)?+[a-z0-9-]++""".r)
}
Given that you'd be comfortable using a regex in Java, it seems like overkill to then try and solve the same problem with a parser in Scala.
Stick with what you know here, but add a Scala twist to clean up the solution a bit. Regexes in Scala also define extractors, allowing them to be used in a pattern match:
//triple-quote to make escaping easier, the .r makes it a regex
//Note how the value breaks normal naming conventions and starts in uppercase
//This is to avoid backticks when pattern matching
val TestRegex = """xxyyzz""".r
class Name(str: String) {
str match {
case Null => throw new IllegalArgumentException("Str must not be null")
case TestRegex => //do nothing
case _ => throw new IllegalArgumentException(
"Str must match 'regex' but was " + str)
}
}
disclaimer: I didn't actually test this code, it may contain typos