Rust println! problem - weird behavior inside the println macro [duplicate] - rust

This question already has answers here:
Why does my string not match when reading user input from stdin?
(3 answers)
Closed 3 years ago.
I am currently working on a simple "user input" program. The user can enter a number, which I get with
std::io::stdin().read_line(&mut let_name_here).ok().expect("Error");. After getting the user input I want to print it to the console for a review.
I have noticed strange behavior within the println! macro. The following code
println!("Your input: {}", let_name_here);
println!("Your input: {}", let_name_here);
outputs this:
Your input: 15
Your input: 15
Why is there an extra \n in the println! marco. From my coding experience I would assume the following:
Your input: 15
Your input: 15
But to achive this output I have to use folloing code:
print!("Your input: {}", let_name_here);
print!("Your input: {}", let_name_here);
I don't understand why the println! marco outputs\n twice. What would I do, if I want to \n at the end of the first line, with those two marcos it would not be possible. Am I missing something important?

It looks like there is a newline character at the end of the string you have read from stdin. The println macro is then adding a newline char to the end resulting in two newlines.
You should strip away the newline character from the end of the text read from stdin, or just use print if you don't want to do that.

Related

How do I print STDOUT and get STDIN on the same line in Rust? [duplicate]

This question already has answers here:
Why does this read input before printing?
(3 answers)
Closed 2 years ago.
The macros println!() and print!() allow you to print strings and variables with and without a trailing newline, respectively. Additionally, the stdin() function provides a function to read a line of user input from STDIN (stdin().read_line(&mut string)).
It should be safe to assume that if the print macro and the read_line function were used consecutively, you should be able to write output and get input on the same line. However, the segments are executed in reverse order when this happens (STDIN is read first, then the statement is printed).
Here is an example of what I am trying to accomplish:
use std::io;
fn main() {
let mut input = String::new();
print!("Enter a string >> ");
io::stdin().read_line(&mut input).expect("Error reading from STDIN");
}
The desired output would be (STDIN represents the point where the user is asked for input, it is not actually printed):
Enter a string >> STDIN
The actual output is:
STDIN
Enter a string >>
On the other hand, the println macro does not reverse the order, although there is still the issue of the trailing newline:
Enter a string >>
STDIN
In Python (3.x), this can be accomplished with a single line, because the input function allows for a string argument that precedes the STDIN prompt: variable = input("Output string")
I separated the task into the print macro and the read_line function after failing to find a solution in the Rust documentation that would allow something similar to the Python example.
stdout gets flushed on newlines. Since your print! statement does not contain nor end in a newline it will not get flushed. You need to do it manually using std::io::stdout().flush()
For example
use std::io::{self, Write};
fn main() {
let mut input = String::new();
print!("Enter a string >> ");
let _ = io::stdout().flush();
io::stdin().read_line(&mut input).expect("Error reading from STDIN");
}
you should be able to write output and get input on the same line.
There is no concept of "same line" in stdin and stdout. There are just different stream, if you want to perform terminal manipulation you should use something that handle terminal, like console.
In Python (3.x), this can be accomplished with a single line, because the input function allows for a string argument that precedes the STDIN prompt: variable = input("Output string")
Well, here you go:
use dialoguer::Input;
let name = Input::new().with_prompt("Your name").interact()?;
println!("Name: {}", name);
https://docs.rs/dialoguer/0.3.0/dialoguer/struct.Input.html#example-usage

'$' regex python [duplicate]

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 5 years ago.
I am trying to understand how '$' works in the re module of python 3.6.
The python documentation says,'$' Matches the end of the string or just before the newline at the end of the string..., which I do not completely understand.
Could you please give me a few basic examples of $'s functionality inre.match?
The $ character always matches the end of the input string.
In Multi-line mode (e.g. when re.M is passed as a flag to one of the re functions), it also matches the end of each line of a multiple line input, just before the newline character.
You want an example with re.match:
some_string = "foo bar baz"
if re.match("foo.*baz$", some_string):
print("Starts with foo and ends with baz") # this will be printed
The $ character in the pattern here ensures that the baz that gets matched occurs right at the end of the input string. That pattern wouldn't match a string like "foo baz bar", since even though baz occurs, it isn't at the end of the input.
It's not usually useful to call re.match with the multi-line flag set. Instead, you'd more commonly do that with something like re.findall:
multi_line_string = """
foo
bar
foobar
barrel"""
for match in re.findall("^bar$", re.M):
print("bar is whole line") # this will get printed only once
The ^ and $ characters in the pattern given to re.findall make sure that bar is the whole contents of the line that gets matched. Without them, foobar and barrel would also match.

How do I write a multi-line string in Rust? [duplicate]

This question already has answers here:
What is the syntax for a multiline string literal?
(5 answers)
Closed 1 year ago.
Is it possible to write something like:
fn main() {
let my_string: &str = "Testing for new lines \
might work like this?";
}
If I'm reading the language reference correctly, then it looks like that should work. The language ref states that \n etc. are supported (as common escapes, for inserting line breaks into your string), along with "additional escapes" including LF, CR, and HT.
Another way to do this is to use a raw string literal:
Raw string literals do not process any escapes. They start with the
character U+0072 (r), followed by zero or more of the character U+0023
(#) and a U+0022 (double-quote) character. The raw string body can
contain any sequence of Unicode characters and is terminated only by
another U+0022 (double-quote) character, followed by the same number
of U+0023 (#) characters that preceded the opening U+0022
(double-quote) character.
All Unicode characters contained in the raw string body represent
themselves, the characters U+0022 (double-quote) (except when followed
by at least as many U+0023 (#) characters as were used to start the
raw string literal) or U+005C (\) do not have any special meaning.
Examples for string literals:
"foo"; r"foo"; // foo
"\"foo\""; r#""foo""#; // "foo"
"foo #\"# bar";
r##"foo #"# bar"##; // foo #"# bar
"\x52"; "R"; r"R"; // R
"\\x52"; r"\x52"; // \x52
If you'd like to avoid having newline characters and extra spaces, you can use the concat! macro. It concatenates string literals at compile time.
let my_string = concat!(
"Testing for new lines ",
"might work like this?",
);
assert_eq!(my_string, "Testing for new lines might work like this?");
The accepted answer with the backslash also removes the extra spaces.
Every string is a multiline string in Rust.
But if you have indents in your text like:
fn my_func() {
const MY_CONST: &str = "\
Hi!
This is a multiline text!
";
}
you will get unnecessary spaces. To remove them you can use indoc! macros from indoc crate to remove all indents: https://github.com/dtolnay/indoc
There are two ways of writing multi-line strings in Rust that have different results. You should choose between them with care depending on what you are trying to accomplish.
Method 1: Dangling whitespace
If a string starting with " contains a literal line break, the Rust compiler will "gobble up" all whitespace between the last non-whitespace character of the line and the first non-whitespace character of the next line, and replace them with a single .
Example:
fn test() {
println!("{}", "hello
world");
}
No matter how many literal (blank space) characters (zero or a hundred) appear after hello, the output of the above will always be hello world.
Method 2: Backslash line break
This is the exact opposite. In this mode, all the whitespace before a literal \ on the first line is preserved, and all the subsequent whitespace on the next line is also preserved.
Example:
fn test() {
println!("{}", "hello \
world");
}
In this example, the output is hello world.
Additionally, as mentioned in another answer, Rust has "raw literal" strings, but they do not enter into this discussion as in Rust (unlike some other languages that need to resort to raw strings for this) supports literal line breaks in quoted content without restrictions, as we can see above.

Breaking the each loop in Groovy [duplicate]

This question already has answers here:
Can you break from a Groovy "each" closure?
(8 answers)
Closed 10 years ago.
How will I break the loop if a particular condition is satisfied?
My input file has around n number of lines. If the required information is got at some mth line I need to break the loop instead of reading the remaining lines.
new File("test.txt").readLines().reverseEach{line ->
println line
if(line.contains("Data"))
break;
}
You could use find to do this. Find ends the loop the first time the closure returns true and returns the last found element.
This
(1..20).find{
println it
it == 5
}
Would be the following in the groovy console.
1
2
3
4
5
Result: 5
You can't just break from closure. You can either throw an exception and exit from it, or do not use closures at all. Read all lines in array/list and iterate through it.

Reading a string with spaces in Fortran

Using read(*,*) in Fortran doesn't seem to work if the string to be read from the user contains spaces.
Consider the following code:
character(Len = 1000) :: input = ' '
read(*,*) input
If the user enters the string "Hello, my name is John Doe", only "Hello," will be stored in input; everything after the space is disregarded. My assumption is that the compiler assumes that "Hello," is the first argument, and that "my" is the second, so to capture the other words, we'd have to use something like read(*,*) input1, input2, input3... etc. The problem with this approach is that we'd need to create large character arrays for each input, and need to know exactly how many words will be entered.
Is there any way around this? Some function that will actually read the whole sentence, spaces and all?
character(100) :: line
write(*,'("Enter some text: ",\)')
read(*,'(A)') line
write(*,'(A)') line
end
... will read a line of text of maximum length 100 (enough for most practical purposes) and write it out back to you. Modify to your liking.
Instead of read(*, *), try read(*, '(a)'). I'm no Fortran expert, but the second argument to read is the format specifier (equivalent to the second argument to sscanf in C). * there means list format, which you don't want. You can also say a14 if you want to read 14 characters as a string, for example.

Resources