I want to create a function in MATLAB by using the plus operator (i.e. plus(a,b)) where when the user passes two strings, they are concatenated together and displayed as the result. However, every time I check on this, I get the error that I cannot implement built-in functions. Is it possible to do this in MATLAB and if it is possible, what is the procedure of doing it?
Any help on this problem is appreciated.
Create a directory called #char
Inside that directory place a function similar to the following:
function c = plus(a,b)
c = horzcat(a,b); %// if you want the result to be output
disp(c) %// if you want the result to be displayed
Ensure that the parent directory of the #char directory is on the MATLAB path (or is the Current Directory).
Use the function
>> 'abc' + 'def'
abcdef
ans =
abcdef
Related
I have a MATLAB script which creates an matrix, 'newmatrix', and exports it as matrix.txt:
save -ascii matrix.txt newmatrix
In my script I also calculate the distance between certain elements of the matrix, as the size of the matrix depends on a variable 'width' which I specify in the script.
width = max(newmatrix(:,5)) - min(newmatrix(:,5))
x_vector = width + 2
And the variable x_vector is defined as width + 2
I want to know is it possible to export x_vector, labelling it as, eg my_vector $x_vector so that "my_vector 7.3" will be produced when the value of x_vector is equal to 7.3
I have tried:
save -ascii 'my_vector' + x_vector
But receive the following errors:
warning: save: no such variable +
warning: no such variable 'my_vector'
Three things:
1) I prefer to use functional form of the calls so that you can pass in variables rather than static strings.
save -ascii matrix.txt newmatrix
is equivalent to:
save('-ascii','matrix.txt','newmatrix')
In other words, in the first form all inputs get treated as string inputs to the function.
2) You can't add character arrays in Matlab. Rather you concatenate them or use sprintf.
name = sprintf('my_vector_%g',x_vector);
save('-ascii',name)
Note by using the functional form we can now pass in a variable. Note however this won't work because name should be either a valid option or a variable, and my_vector_7.3 isn't either.
3) I'm not entirely sure what you're asking, but I think you want the text file to say "my_vector 7.3". I don't think -ascii supports strings .... You could write something using fprintf.
fid = fopen('matrix.txt','w');
fprintf(fid,mat2str(new_matrix));
fprintf(fid,'\n');
fprintf(fid,'my_vector %g',x_vector);
fclose(fid);
Let's just say I type 2+3 in MATLAB. It gives me this output :
>> 2+3
ans =
5
Why is the output coming after 2 newlines? How do I correct this ?
Ideally, I would get the following output
ans = 5
You can use the format command to change how the display of variables when printed. In your case, you'll likely want to use the 'compact' option
format compact
This will remove all of the unnecessary newlines.
2+3
% ans=
% 5
Unfortunately, there is no built-in way to display it all on the same line because MATLAB's display is built to deal with multi-dimensional data. You could overload the display command if you really wanted. You can create a folder named #double and then a function named display inside of that
#double/
display.m
Then inside of display.m you could do something like this
function display(x)
% If it's a scalar, then show it all on one line
if isscalar(x)
fprintf('%s = %g\n', inputname(1), x);
else
% Otherwise use the built-in display command
builtin('display', x)
end
end
Then it will automatically be used when you have a double variable
>> 2 + 3
% ans = 5
If you wanted to overload the display of other types of data (uint16, int8, uint8), you would need to do the same as above except put a copy within their # folders as well.
Considering the following code
x = input('Input an array: ');
If the user types [1 2 3], variable x will be assigned that numeric vector. Similarly, if they type {1, [2 3], 'abc'}, variable x will be a cell array containing those values. Fine.
Now, if the user types [sqrt(2) sin(pi/3)], variable x will be assigned the resulting values: [1.414213562373095 0.866025403784439]. That's because the provided data is evaluated by input:
input Prompt for user input.
result = input(prompt) displays the prompt string on the screen, waits
for input from the keyboard, evaluates any expressions in the input,
and returns the value in result. [...]
This can cause problems. For example, what happens if the user types addpath('c:\path\to\folder') as input? Since the input is evaluated, it's actually a
command which will be executed by Matlab. So the user can get to add a folder to the path. Worse yet, if they input path(''), the path will be effectively changed to nothing, and Matlab will stop working properly.
Another potential source of problems is that
[...] To evaluate expressions, input accesses variables in the current workspace.
For example, if the user inputs fprintf(1,'%f', varname) and varname is an existing numeric array, the user will know its current value.
This behaviour is probably by design. Users of a Matlab program are trusted when inputting data, much like they are trusted not to press Control-C to halt the program (and then issue all commands or inspect all variables they like!).
But in certain cases the programmer may want to have a more "secure" input function, by which I mean
prevent any function calls when evaluating user
input; and
prevent the input from accessing variables of the program.
So [1 2] would be valid input, but [sqrt(2) sin(pi/3)] or path('') would not because of item 1; and [1 2 3 varname(1)] would be invalid too because of item 2.
I have found a not very satisfactory solution (and I'd love to read about a better one). It uses a semi-documented function and implies saving the user input to a temporary file. The function, referred to in Yair Altman's blog, is getcallinfo. According to help getcallinfo:
getcallinfo
Returns called functions and their first and last lines
This function is unsupported and might change or be removed without
notice in a future version.
This function solves issue 1 (prevent function calls). As for issue 2 (prevent access to variables), it would suffice to evaluate the input within a function, so that it can't see other variables. Apparently (see example 2 below), getcallinfo detects not only called functions, but variables too. Anyway, it's probably a good idea to do the evaluation in the isolated scope of a function.
The procedure is then:
Use the string version of input to prevent evaluation:
x = input('Input an array: ', 's');
Save the string to a file:
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
Check the input string with getcallinfo to detect possible function calls:
gci = getcallinfo(filename);
if ~isempty(gci.calls.fcnCalls.names)
%// Input includes function calls: ignore / ask again / ...
else
x = evalinput(x); %// evaluate input in a function
end
where evalinput is the following function
function x = evalinput(x)
x = eval(x);
Example 1
Consider
x = input('Input an array: ', 's');
with user input
[sqrt(2) sin(pi/3)]
Then
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
produces a non-empty gci.calls.fcnCalls.names,
>> gci.calls.fcnCalls.names
ans =
'sqrt' 'sin' 'pi'
which tells us that the user input would call functions sqrt, sin and pi if evaluated. Note that operators such as / are not detected as functions.
Example 2
y = [10 20 30];
x = input('Input an array: ', 's');
User enters
[1 y y.^2]
Then
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
gci = getcallinfo(filename);
produces
>> gci.calls.fcnCalls.names
ans =
'y' 'y'
So variables are detected by getcallinfo as if they were functions.
If I understand your question correctly, it is possible to use regular expressions to accomplish what you are trying to do.
No function or variable calls
At its simplest, this checks to making sure there are no alphabetical characters in the input string. The expression would then be, for x containing input:
expr = '[a-zA-Z]';
x = input('Input an array: ', 's');
valid = isempty(regexp(x,expr));
This alone works for the few examples you give above.
Allowing some functions or variables
Suppose you want to allow the user to access some variables or functions, maybe simple trig functions, or pi or what have you, then it's no longer so simple. I've been playing around with an expression like below:
expr = '(?!cos\(|pi|sin\()[a-zA-Z]+
But it doesn't quite do what is expected. It will match in( in sin. If you know regex better than I, you can massage that to work properly.
Otherwise, an alternative would be to do this:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x)',''),expr))
so that you remove the strings you are interested in.
Hope this helps.
Update: In order to allow imaginary/exp values, and paths
The new expression to match becomes
expr = '[iIeE][a-zA-Z]+';
This ignores i/I and e/E (you can augment this as you see fit). You can also do a two character limit by switching to \{2,}, though I people can still have one character anonymous functions..
The other part, to check for input becomes:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x|''(.*?)'')',''),expr))
now you can exclude custom functions (you can always have this as an array and join them together by a |) and paths.
Here are a few examples tested along with the usual:
Passes
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
Fails
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'
I have a function that goes something like this:
function [] = function1
-variable1= value1;
-variable2= value2;
-matrix1=[]
-matrix2=[]
-loops that fill in matrix1 and matrix2
-more declarations
-final function1 end
function2[]
takes values from function 1 and does stuff, creates new variables
funcion2 end
function3[] that uses values from function 2 and function4[] that uses function 3.
(Sorry for all of that by the way). Now, my question is, is there anyway to save variables, arrays, etc. in the workspace for later analysis? All 4 functions are on the same tab in the MATLAB editor.
To save any particular variable from workspace in Matlab you should execute the following
save('Name of the mat file','Name of the variable')
To save multiple variable the command shall be
save('name of the mat file','var1','var2'...)
variable can be array, matrix, structure, double anything. For any other use of the function save please docsearch it in the command prompt
kinda new to matlab here, searching the csvwrite tutorial and some of the existing webportals regarding my question couldn't find a way to pass my variables by value to the output file names while exporting in csv; providing my bellow scripts, i would like to have the output files something like output_$aa_$dd.csv which aa and dd are respectively the first and second for counters of the scripts.
for aa=1:27
for dd=1:5
M_Normal=bench(aa,dd).Y;
for j=1:300
randRand=M_Normal(randperm(12000,12000));
for jj = 1:numel(randMin(:,1)); % loops over the rand numbers
vv= randMin(jj,1); % gets the value
randMin(jj,j+1)=min(randRand(1:vv)); % get and store the min of the selction in the matix
end
end
csvwrite('/home/amir/amir_matlab/sprintf(''%d%d',aa, bb).csv',randMin);
end
end
String concatenation in MATLAB is done like a matrix concatenation. For example
a='app';
b='le';
c=[a,b] % returns 'apple'
Hence, in your problem, the full path can be formed this way.
['/home/amir/amir_matlab/',sprintf('%d_%d',aa,bb),'.csv']
Furthermore, it is usually best not to specify the file separator explicitly, so that your code can be implemented in other operating systems. I suggest you write the full path as
fullfile('home','amir','amir_matlab',sprintf('%d_%d.csv',aa,bb))
Cheers.