问题
I have a read statement that expects a number, very simple example code:
program test
integer var
read(*,*) var
end
The thing is that I usually input a string of characters (ie: yes) on account of being distracted. How can I prevent my code from halting entirely and instead display an error message of the type You've entered an incorrect value. Try again?
I'm thinking something like:
program test
integer var
10 read(*,*) var
if (var.not.a.number) then
write(*,*)'You've entered an incorrect value. Try again'
goto 10
endif
end
What would that var.not.a.number condition look like?
I use gfortran
to compile under Ubuntu.
Edit: Thank you all! I ended up implementing HPM's 3rd option since it was the simplest one:
program test
integer var,iostat,ios
10 read(*,*,iostat=ios) var
if (ios.ne.0) then
write(*,*)'You've entered an incorrect value. Try again'
goto 10
endif
end
Special thanks to User7391
who took the effort to write all that code!
回答1:
You're using list-directed input. The second *
in the statement read(*,*)
essentially tells the compiler/run-time system that you will provide it with something at run time that can be interpreted as an integer
. If you want to give yourself the freedom to make mistakes on input you have (at least) 3 choices.
- You can, as @User7391's answer already says, read the input into a character variable and parse it yourself. That kind user has even offered to write the code for you !
- You could modify the read command to something like
read(*,*,err=1234)
where1234
is the label of your error-handling statement(s). This approach is now considered rather old-fashioned and might be frowned upon. - You could modify the read command to something like
read(*,*,iostat=ios)
whereios
is an integer variable which catches theiostat
(i/o status flag) reported by theread
statement. You might then write the lineif (iostat/=0) ...
for error handling. This is considered to be the more up to date approach.
回答2:
Perhaps you could read in the value into a character variable and then process that character variable accordingly.
If it contains only numbers, store it in var, else, report an error and loop back around.
To check if a character is only numeric, consider this example code:
PROGRAM test
CHARACTER(len=100) :: input
LOGICAL :: is_numeric, success
INTEGER :: var
DO
READ(*,*) :: input
IF (is_numeric(input)) THEN
READ(input,*) var
success = .TRUE.
ELSE
WRITE(*,*) 'ERROR: Input is not numeric.'
END IF
IF (success) THEN
break
END IF
END DO
END PROGRAM test
LOGICAL FUNCTION is_numeric(string)
IMPLICIT NONE
CHARACTER(len=*), INTENT(IN) :: string
LOGICAL :: is_numeric
INTEGER :: var
INTEGER :: error_val
READ(string,*,IOSTAT=error_val) x ! This line converts string to an integer
! If there was an error, the error_val variable is
! non-zero
is_numeric = error_val==0
END FUNCTION is_numeric
Tell me if you need help with writing the example code.
You'd need to be able to convert a character to an integer. This is possible with internal read/write statements.
回答3:
Using old FORTRAN:
90 continue
read (*, *, err=90) number
This can be made more elaborate, where you test for the error and output an error message.
来源:https://stackoverflow.com/questions/12145774/prevent-fortran-from-closing-when-a-character-is-inputed-instead-of-a-number