Is it possible to go from within a case in switch to another case based on a condition?
Here is an example:
flag_1 = 'a'
flag_2 = 1;
x = 0;
switch flag_1
case 'a'
if flag_2 == 1
% go to otherwise
else
x = 1;
otherwise
x = 2;
end
If flag_2 == 1 I want to go from case 'a' to otherwise. Is it possible?
No, this is not possible. There’s no “goto” statement in MATLAB.
One solution is to put the code for the “otherwise” branch into a function, then call that function if your condition is met:
flag_1 = 'a'
flag_2 = 1;
x = 0;
switch flag_1
case 'a'
if flag_2 == 1
x = otherwise_case;
else
x = 1;
otherwise
x = otherwise_case;
end
function x=otherwise_case
% assuming this is more complex of course
x = 2;
end
Similar to Cris' answer, you could set a flag, and have a simpler conditional based on that flag after the switch:
flag_1 = 'a'
flag_2 = 1;
x = 0;
otherwise_case = false;
switch flag_1
case 'a'
if flag_2 == 1
otherwise_case = true;
else
x = 1;
otherwise
otherwise_case = true;
end
if otherwise_case
% assuming this is more complex of course
x = 2;
end
This is simpler if, for instance, the otherwise_case function would have lots of required inputs which are already available in the current scope when using the flag approach instead.
For completeness, I'm going to mention the "early bailout" approach. Basically, you put your switch inside a try/catch:
try
switch flag_1
case 'a'
if flag_2 == 1
throw(...)
else
x = 1;
otherwise
throw(...)
end
catch ME
% otherwise case, if exception is as expected
end
I should note that the other answers are likely more suitable for the present problem. This approach is useful when you have multiple loops or internal functions within the case, and you want to quickly exit all of them and reach the "otherwise". Note that when doing this you should check within the catch clause that the exception is as you expect (example), to avoid legitimate issues that might arise in the cases' logic.
Related
I'm quite new in MATLAB. I have to write a function that counts the number of a certain character in a text file. 2 input arguments are requested: fname (char vector of the filename) and character (the char it counts in the file).
Output argument: the number of characters found. If the file is not found or character is not a valid char, the function return -1.
I wrote a function which passed correctly two of the 4 tests. The two wrong ones are:
==> 1) Test with all visible characters
Explanation: Variable charnum has an incorrect value. When testing with '#' your solution returned -1 which is incorrect. (0)
==> 2) Non existent file
For number 2), no explanation provided.
This is my code:
function charnum = char_counter(fname, character)
A = fileread(fname);
char_1 = strfind(A, character);
charnum = numel(char_1);
if isfile(fname) == 0 %doesn't work...
charnum = -1;
elseif exist(fname) == 0
charnum = -1;
elseif charnum == 0
charnum = -1;
elseif ischar(character) == 0
charnum = -1;
fclose(fid);
end
Thank you all for your suggestions and advice.
I understand, for the 1) that I probably should add an instruction to take into account all the characters but I can't find a satisfying way that works. Because when I test for the character '#', it works correctly on my MATLAB:
When I test the function with the visible character '#' the answer is correct.
For 2) I don't understand why my 4th line doesn't work correctly.
I already check various options found on the Internet but so far it did not fix the problem.
To answer your questions:
1) A = fileread(fname) will throw an error before you can get to the if statements, so you will have to restructure your code to take that into account.
However, you can use the isequal function to compare two things for an if statement. isfile returns a 0 if the file is not found, so you can compare that to 0.
if isequal(isfile(fname),0)
charnum = -1;
2) The function ischar returns 0 if the input is not a character array. This will return 0 for string arrays, so make 100% sure your input is a character array. Use char to do this:
elseif isequal(ischar(char(character)),0)
charnum = -1;
Here is what your function could look like:
function charnum = char_counter(fname, character)
if isequal(isfile(fname),0)
charnum = -1;
else
A = fileread(fname);
char_1 = strfind(A, character);
charnum = numel(char_1);
if isequal(exist(fname),0)
charnum = -1;
elseif isequal(charnum,0)
charnum = -1;
elseif isequal(ischar(char(character)),0)
charnum = -1;
end
fclose(fid);
end
end
This recursive function takes two input arguments, The first (A) is a number and the second (n) is a digit, checks the occurrence of n in A. (A is updated by removing its last digit in each recursion). it seems like the recursion is infinite and the base case (A == 0) is not valid but why.
function counts = countn(A,n)
if (A == 0)
counts= 0;
end
if (n == mod(A,10))
disp(A);
disp(floor(A/10));
disp(mod(A,10));
B = floor(A/10);
counts = countn(B,n) + 1;
else
B = floor(A/10);
countn(B,n);
end
end
It does not stop because it first evaluates the first if statement if( A == 0) and afterward the if (n == mod(A,10)) where it jumps in the else branch and recursively calls the function again. So it does not stop in the first if statement as you likely expected it to do.
something like this should work:
function counts = countn(A,n)
if (A == 0)
counts = 0;
elseif (n == mod(A,10))
disp(A);
disp(floor(A/10));
disp(mod(A,10));
B = floor(A/10);
counts = countn(B,n) + 1;
else
B = floor(A/10);
counts = countn(B,n);
end
end
You also have to update count counts variable in the else branch to avoid the uninitialized use of variables.
Have a look at how to use a debugger manual. Simply click on the line number inside your function and run your code. Use the F10 and F11 keys to evaluate your code line by line. This helps you understand what your program does.
I'm trying to write a code in MATLAB that has the user input two values. I already have everything written for the input part and I saved the two inputs into two variables: value1 and value2.
What I'm trying to do is use the input values in the matter of:
if value1 = 2
output_result=10
if value1 = 3
output_result=20
and so on.
I've been trying to write an if-elseif statement but I can't seem to figure it out.
Do a switch statement
switch value1
case 2
result = 10;
case 3
result = 20;
...
otherwise
statements
end
If you really want to use an if statement, do this:
if value == 1
result = 10;
elseif value == 2
result = 20;
elseif
%// Put more statements
...
elseif
%// Put even MOAR statements
...
...
else
%// Default case - optional
end
However, the switch statement as per #kkuilla is more elegant. Also note that the else statement is optional. You'd only put this in if everything else fails and want to use a default case.
Here's my code:
N = 1:999;
for i = N
if rem(i,3) == 0 || rem(i,5) == 0
v(i,1) = i
end
end
Te problem is that I get an Array with some zeros in, but I just want an an arraywith the values comforming to my conditions.
How can I fix it?
Thank you!
I think the OP is looking for a result like:
v= N( (rem(N,3)==0) | (rem(N,5)==0) );
though without looping... :-)
I'm assuming that you're using a loop for a reason, and am not removing it from my solution. However, loops should be avoided where possible.
If I understand your question, you're trying to store only those values of i which correspond to a true conditional evaluation. You're problem is that you're using i as your index value inside the assignment statement. Use the end index keyword. Like so:
N = 1:999;
v = [];
for i = N
if rem(i,3) == 0 || rem(i,5) == 0
v(end+1) = i
end
end
The following is only a simple example to generalize and illustrate the problem I am having.
If I have a function like the following:
function newtraph(initialguess,funct,dfunct)
ht = funct(initialguess);
if abs(ht) < 10^(-6)
disp(initialguess); return
elseif abs(ht) > 10^6
disp('Fix Guess'); return
end
newtraph(initialguess-(ht/dfunct(initialguess)), funct, dfunct);
The only way (that I am aware of) to exit out is through the use of those return statements. But, I want to assign output from functions of this variety to variables in the base workspace. I want to do some thing like:
function out = newtraph(initialguess,funct,dfunct)
ht = funct(initialguess);
if abs(ht) < 10^(-6)
out = initialguess; return
elseif abs(ht) > 10^6
disp('Fix Guess'); return
end
newtraph(initialguess-(ht/dfunct(initialguess)), funct, dfunct);
This doesn't work, the return prevents out from being assigned.
Output argument "out" (and maybe others) not assigned
Some ideas I have for a solution are using globals or evalin. But is there some simpler way that I am missing. I just want pass the output from functions of this style back to the base workspace?
A test case, just in case:
funct=#(x) -x-cos(x); dfunct=#(x) sin(x)-1; initialguess=1;
Thanks for your time.
Well, I am an idiot. It was simply a case of forgetting the final assignment:
function out = newtraph(initialguess,funct,dfunct)
ht = funct(initialguess);
if abs(ht) < 10^(-6) %Tolerance
out = initialguess; return
elseif abs(ht) > 10^6
out=0; return
end
out = newtraph(initialguess-(ht/dfunct(initialguess)), funct, dfunct);
Thanks for the quick help!
Your example function that doesn't work is almost there. You just need to assign
out = newtraph(...)
on the last line so you can capture the output.
You probably also need to assign out = 0 or some dummy value when you report "fix guess" so that branch of the code will also return a value.
Just a guess here: aren't you missing the assignment in the last line? And also don't you need to initialize out in your elseif in case out wasn't assigned before? I.e.
ht = funct(initialguess);
if abs(ht) < 10^(-6)
out = initialguess;
return
elseif abs(ht) > 10^6
disp('Fix Guess');
if ~exist('out')
out=1; % you need some default value if you ever reach this code without ever initializing out
end
return
end
out = newtraph(initialguess-(ht/dfunct(initialguess)), funct, dfunct);
This answer may be a little late, but I think that it is important enough to deserve to be pointed out here. To make the recursion clearer I do recommend another approach here.
function out = newtraph(initialguess,funct,dfunct,counter)
maxCount = % yourValue;
ht = funct(initialguess);
if abs(ht) > 10^(-6) || abs(ht) < 10^6 || counter<maxCount % Break out after x tries
counter = counter+1;
out = newtraph(initialguess-(ht/dfunct(initialguess)), funct, dfunct,counter);
elseif abs(ht) < 10^(-6) %Tolerance
out = initialguess;
else
warning('Convergence were not reached!');
out=0;
end
The preffered structure may be personal, but this way it is clear that you keep going until you hit a stop criterion, namely the function converged or were divergent.
Also, recursive functions are dangerous due to that the only way to stop them is to fulfill the exit criterion or when the program crashes. Matlab have a limit of how many times a recursion can go on and then throws an error. You will most likely want to handle the error by yourself (like you have done already by setting out=0;). Also matlabs limit is 500 recursive calls and you do most likely want to terminate the function earlier, maybe at 8-20 calls, depending on your algorithm.