This question already has answers here:
Why does my string not match when reading user input from stdin?
(3 answers)
Closed 2 years ago.
When parsing a String type value to a floating-point type value in Rust, everything works fine with"let pi: f64 = 3.14".parse().unwrap();.
However, when parsing a String type value that comes from standard input, even if it's the exact same value, the program panics and throws:
thread 'main' panicked at 'called Result::unwrap() on an Err
value: ParseFloatError { kind: Invalid }', src/libcore/result.rs:999:5
note: run with RUST_BACKTRACE=1 environment variable to display a
backtrace.
I checked the value's type, and it is a String, so I don't understand what the error is about, and I haven't been able to find anything related specifically to standard input (stdin) and this issue. Has anyone else come across this? Is there a good way to prevent the panic?
Here is some code to replicate the issue:
use std::io::{stdin,stdout,Write};
fn main() {
let mut s = String::new();
println!("Give a number ");
stdin().read_line(&mut s)
.expect("Did not enter a correct string");
let user_input: f64 = s.parse().unwrap();
println!("{:?}", user_input)
}
Thanks in advance!
As suggested by SCappella the new line needs to be removed.
The following will work:
let user_input: f64 = s.trim().parse().unwrap();
Much thanks to Jeff Muizelaar and SCappella!
SCappella pointed out that there is a newline character causing the type conversion to fail, and Jeff Muizelaar pointed out that adding a trim() method to the String, "s," would remove the newline, resolving the issue.
After realizing that was the issue, I was able to do some more accurate Googling and found this bit of Rust documentation. It explains that the read_line() method
"read[s] all bytes until a newline (the 0xA byte) is reached...Once found, all
bytes up to, and including, the delimiter (if found) will be
appended..."
Related
This question already has an answer here:
How to read one character at a time from user input — at each keystroke (without waiting for the user to press the return key)?
(1 answer)
Closed 2 months ago.
I'm trying to read from the standard input by using input_byte stdin
Something like this:
let rec loop () =
Format.eprintf "in the loop#.";
(match input_byte stdin with
| 0x0D -> print_newline ()
| b -> Format.eprintf "saw %i#." b);
loop ()
let () =
loop ()
If I type aaa I expect to see
in the loop
a
in the loop
saw 97
a
in the loop
saw 97
a
in the loop
saw 97
But instead nothing happens until I hit enter and this is what I have:
in the loop
aaa
saw 97
in the loop
saw 97
in the loop
saw 97
in the loop
saw 10
in the loop
Is there a way to read characters from a channel with a reader that doesn't wait for a flush?
Generally speaking the terminal driver of your system doesn't send characters at each keystroke. As you're seeing, it waits to send a whole line. This is more efficient and it also lets you correct errors before sending.
There are system-dependent ways to change this buffering behavior (and also echoing behavior, which you might also want to change). If you're on some kind of Unix system (anything but Windows essentially) you can use Unix.tcsetattr to change the handling of characters by the terminal driver.
Here is a previous question and answer that shows how to read one character at a time: How to read a character in OCaml without a return key?
i use C++ in CODE:BLOCKS and ive made a little game with login, so when i wanna compare a variable(int) that came from scanf and a variable that i made, that wont work. So in the program i log in with a name and a pw, that works, than i get an exercise like: 65+34 and if i type ANY numbers, it will crash, if i enter a letter, it will say "A valasz rossz" that means my answer is incorrect, sorry for the hungarian program... translates:
A valasz helyes - answer is right
A valasz rossz - answer is wrong
Jatek! Valaszolj a helyesen- Game!Answer correctly
Bejelentkezes! - Login
Felhasznalonev - Nickname
Jelszo - pawssword
On meg nem regisztralt! 1 Regisztracio 2 Kilepes - U havent
registered yet! 1 register 2 Exit
So i think the problem is at the criterion if(ans==eo)
CODE:http://pastebin.com/E0AbRx8y HELP AT 104. LINE
Thanks for helping, it would be a lot for me! <3
In line 103, you need to pass scanf the ADDRESS of the variable where you want to store the value, so instead of:
scanf("%d",ans);
You should do:
scanf("%d", &ans);
You probably need to review all your calls to scanf and:
Ensure that you pass a pointer to the output variable
Check the return value in order to verify that you've read successfully the user's input (e.g. detect if you expect a number and the user enters a word)
Use C strings (arrays of char, which work with the printf and scanf functions) instead of C++ strings (std::string, which work with the >> and << operators)
Hope that it helps.
The problem is here :
scanf("%d",ans);
'scanf()' stores values, so it needs a place to store them.
This is done by providing the addresses (in pointers) of
where to store the values.
So write:
scanf("%d",&ans);
It will solve your problem.
I am trying to compile someone else's FORTRAN code using gfortran 4.4.6. The original coder used something like Compaq FORTRAN.
The code in question is supposed to read a filename like 'foo.txt' and create a new file called 'foo_c.txt':
file_label_end = SCAN(filename, '.') - 1
WRITE (output_filename,5) filename
5 FORMAT (A<file_label_end>, '_c.txt' )
gfortran complains about the opening angle bracket of the character specifier. That is, rather than "A3" he has "A<(a variable with value 3)>". I cannot find any information about interpolating format widths from variables... Is this possible? If not, what's the best way to fix this?
Update:
This seems to be working (compiling):
file_label_end = SCAN(par_filename, '.', .TRUE. ) + 1
output_filename = par_filename(1:file_label_end) // '_c.par'
but I later have a similar case:
12 FORMAT (<n-1>F10.5)
...
READ(1,12) (cat_parm (blk,j), j = 1,n-1)
which I attempted to fix by creating a format string:
write(fmt12,'(I0,A4)') n-1, 'F10.5'
!12 FORMAT (fmt12)
12 FORMAT (fmt=fmt12)
But the "t" in "fmt" gets flagged with an error about "Nonnegative width required in format string"
The use of <> in Fortran edit descriptors is non-standard, though widely implemented. You certainly can build edit descriptors from variables, the standard way is through an internal write, something like this (omitting declarations):
format_string = ''
write(format_string,'(a1,i0,a6)') 'A', file_label_end,'''_c.txt''' ! WARNING I haven't tested this
and then
write(output_filename,fmt=format_string) filename
But in your case this is not entirely necessary. You could try this instead
file_label_end = SCAN(filename, '.') - 1
WRITE (output_filename,'(a)') filename(1:file_label_end)//'_c.txt'
With the 'a' edit descriptor omitting a width means that all the characters in the expression will be written. You may want to declare
character(len=*), allocatable :: output_filename
if you haven't already done so.
The easiest is to use modern fortran
WRITE (output_filename,'(a)') trim(filename) // '_c.txt'
Otherwise I would write the number in the format string using a similar internal write.
I'm currently porting an application from Fortran to C and need to output some variables to compare results. I'm very new to Fortran, and although i understand the code and have now ported several thousand lines, I'm a noob at writing Fortran code myself.
This code:
write(6,'(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)') 'iHyd:',
& ih,'; dzdr: ',dzdr,'; tauray:', tauRay,'; zRay: ',
& zray,'; ampRay: ',realpart(aray),'+j*',
& imagpart(aray),'; qRay: ',qray,'; width :',w
Compiles fine, but when run, the program exits with:
At line 296 of file calcpr.for (unit = 6, file = 'stdout')
Fortran runtime error: Expected INTEGER for item 15 in formatted transfer, got REAL
(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)
^
q0: 1432.3944878270595
nArrayR: 501 nArrayZ: 201
iHyd: 1; dzdr: ************; tauray:************; zRay: ************; ampRay: NaN+j* NaN
; qRay:
Besides being really ugly, it doesn't make much sense to me, as ìh is declared as integer*8 and not as real.
So how can i solve this?
I'm counting 6 character&variable specifications in the format statement, but you're printing 8 of them.
edit:
a nicer use of the format statement would be '(A,I3,7(A,E12.8))'
Fortran "recycles" the format if there are more things to be printed than specified in the format statement. If a write statement gives results you don't understand, to diagonose the problem it may be helpful to remove the things printed one at a time until the error goes away.
It says "item 15", which I would take to be down near the end of your list, not ih at the beginning. It's clear that both "w" and "qray" are being printed as REAL; is either one of them an INTEGER? You may need to change the format specifier then.
I am working on a simple application written in C. I am working in a Unix environment.
My application is doing some simple I/O. I use printf to prompt the user for some input and then use scanf to get that input.
The problem is, I don't know how to tell my application that I am ready to proceed after entering in a value. Typing 'enter' provides a newline '\n' which makes sense. Control-d does allow scanf to capture my input but seems to ignore any subsequent scanf instructions.
Can someone help me out?
printf("Enter name\n");
scanf("%s",input);
printf("%s",input);
printf("enter more junk\n")
scanf("%s",morestuff); /* cntrl+d skips this*/
Check the return value from scanf(). Once it has gotten EOF (as a result of you typing control-D), it will fail each time until you clear the error.
Be cautious about using scanf(); I find it too hard to use in the real world because it does not give me the control over error handling that I think I need. I recommend using fgets() or an equivalent to read lines of data, and then use sscanf() - a much more civilized function - to parse the data.
See also a loosely related question: SO 3591642.
[EDIT: This answer is incorrect, as I stated below, I'm learning as well]
Have you tried CTRL-Z?
That sends EOF to scanf, which, according to its man page, should make scanf move to the next field. As you've entered only a string as the input format, that should terminate the scanf.
I can't test this right now, but you can give it a shot.
Man page is here:
http://www.slac.stanford.edu/comp/unix/package/rtems/doc/html/libc/libc.info.scanf.html