Validate number in function from user input

7 views (last 30 days)
Hi there,
I am having some trouble debugging my function. When I run, it seems to bug on the while loop but I cannot figure out why after several attempts.
I would like to have the user input a positive number or empty value, []. If not, repeat the input prompt. In addition, I must use str2double to convert text strings.
MY FUNK:
function valid_number = ask_for_number()
txt_input = input ('Enter a number:\n\n','s');
valid_number = str2double(txt_input);
if (nargin > 1);
error('Enter a single number');
txt_input = input('Enter a number:\n\n', 's');
end
while valid_number <=0;
fprintf('\n The number entered must be positive or empty \n\n');
txt_input = input ('Enter a number:\n\n');
end
if ~isnumeric(valid_number);
txt_input = input ('Enter a number:\n\n','s');
end
if (isempty(txt_input) & isnan(txt_input));
valid_number = [];
end
valid_number = str2double(txt_input);
end
Merci beaucoup for your help.

Accepted Answer

Stephen23
Stephen23 on 5 Feb 2015
Edited: Stephen23 on 6 Feb 2015
There seems to be quite a bit of confusion here. I suspect that a few bits of the code that do not actually do what you want them to do. Lets go through the function as it is:
  • You use input('prompt text','s'), which is great. A very robust and healthy choice. Note that specifying the 's' option means that input returns a string.
  • The line if (nargin >1) makes no sense, because nargin actually tell us how many input arguments there are to the function it is within, which in this case you have defined as ask_for_number(). Those parentheses are empty so there are exactly zero input arguments possible, and this boolean will therefore always be false. If you want to check that the user did not enter multiple numbers after the input prompt, then you need to use a different tool.
  • The code inside the while loop does not change the loop variable valid_number, which is used to break the condition. So if the first number is negative it will never break out of this loop. Try it, and you be trapped forever in this loop.
  • The line ~isnumeric(valid_number) does nothing useful at all, which you discover when you read the documentation for str2double: if str does not represent a valid scalarvalue, str2double returns NaN. Because NaN is numeric, this test will always be false, regardless of what characters the user enters.
  • The line isempty(txt_input) & isnan(txt_input) also does nothing useful. If the user does not enter any characters or digits and simply presses enter after the input prompt then txt_input will be empty, so isempty(..) will be true. However as we noted in the very first point above, the function input returns a string, and isnan is a test for a numeric NaN value. Passing it any string, even 'NaN', will return false. So this line will never be true, and the code following it will never run.
You seem motivated to write code, and this is what you should do:
  • start again from an empty function.
  • Use the documentation. The lovely people at MathWorks put it there for a reason, and the more you use it the more useful it becomes.
  • write one line at a time, or some minimal amount for loops and the like.
  • test each line after you write it. Use disp or the debugger, or whatever tool you feel comfortable with to check that the values are correct.
  • Write down a list of test cases as you are writing your code. Every time you find a test case that you want your code to handle, ans also for every failure or special case, write it down. Use this list for testing your function.
  • If you want to do something, and you are not sure how, look on the internet for answers and examples, look at the documentation (it has working examples!), and if that does not work, come back here and ask us.

More Answers (2)

dpb
dpb on 5 Feb 2015
nargin checks for number of arguments into the called function; your function doesn't have room for any so that whole clause is useless. If your intent is to test whether there were two or more discernible values returned from parsing the input string by str2double, use
if numel(valid_number)>1
But, for the user to do this requires they surround the input string in curlies and create a valid cell array of strings so is highly unlikely altho it doesn't hurt to check.
More to your actual question pose, you've got the while loop enclosing only an input statement and then the function continues on down to the end before it tries to evaluate it. At that point there is no more checking however, whatever is the result of the last str2double call is what your function will return regardless of all the other testing.
You need the while...end loop to enclose essentially the entire function body and use a logic variable to control it rather than the result...
isOK=false;
while ~isOK
txt_input=input(...
valid=str2double(txt);
if numel(valid)==1 & valid>0
isOK=true; % ok, we can quit
else
...various errors here...
end
...
end
  4 Comments
dpb
dpb on 5 Feb 2015
...How will the user ever be able to define a cell array of strings from the prompt of input('...','s') ?...
As precisely written, can't, agreed. It was a description of what inferred OP had in mind when trying to write the testing, not intended as literal, necessarily.
Something as simple as removing the 's' parameter from the input or more diabolical (but surely not unheard of and particularly often with newbies) is an eval. will work quite nicely, however....
>> s=input('enter: ')
enter: {'2','3'}
s =
'2' '3'
>> str2double(s)
ans =
2 3
>> >> s=input('enter: ','s')
enter: {'2','3'}
s =
{'2','3'}
>> eval(s)
ans =
'2' '3'
>> str2double(ans)
ans =
2 3
>>
Stephen23
Stephen23 on 6 Feb 2015
Edited: Stephen23 on 6 Feb 2015
True, removing the 's' could allow this situation to occur, and your suggestion of "defensive programming" to check for this works well. I guess for me getting them to understand the functionality is the first priority, which makes this check unnecessary. Although in this circumstance you are probably right: this small change could occur quite easily and without the OP being aware of its ramifications, which makes the small bit of extra code required worthwhile.

Sign in to comment.


PR
PR on 5 Feb 2015
Thank you dpb and Stephen for your suggestions.
I especially appreciate your pedagogical perspective Stephen as I am just beginning my journey
in Matlab. I will keep working it at using a line by line approach.
Cheers
  1 Comment
Stephen23
Stephen23 on 6 Feb 2015
Edited: Stephen23 on 6 Feb 2015
It is daunting starting to learn something new, but it just takes time... good luck and enjoy the journey! And of course, come and ask questions if things don't make sense. Use the internet too, there are a million examples online. And of course do not forget the Documentation :)

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!