I have a character array, cA, and each entry of each stores a single character, such as 'a', '(', '[', and ' '.
My program will iterate this array and perform a certain type of operation based on the content of each entry. For example,
if (cA(i) == 'a') do sth; end
For the characters such as 'a' , 'b', the above character comparison operation is trivial.
But how can I handle the special characters such as '(', '[' and ' '( a blank space)
Can I write something such as
if (cA(i) == ' ')
if (cA(i) == '(')
In general, I suggest comparing strings using STRCMP, e.g.
if strcmp(cA(i),'('), doSomething, end
For your specific case, I suggest a SWITCH/CASE statement. Note that in Matlab, this doesn't fall through like in c; instead, only the "good" case gets executed. In my experience, this helps readability. Thus
for myChar = cA %# this loops over every char in the 1-by-n string
switch myChar
case 'a'
do something
case 'b'
case {'c','d'} %# this is how you handle multiple chars with the same outcome
otherwise
error('char %s not handled',myChar) %# don't forget this
end
end
Did you try it and get an error? Because it works for me:
c = '(';
if(c == '(')
disp('left paren')
end
This prints left paren, as expected.
Related
I have a function I cannot change in Matlab that converts CSV file to a 1d array of chars.
This is an example of what it looks like:
array_o_chars = ['1' 'd' ',' ' ' 'a' 'r' 'r' 'a' 'y' '\n' 'o' 'f' ',' ' ' 'c' 'h' 'a' 'r' 's'];
I need to convert it to a 2d "Cell" array for the rest of my code, how do I do it?
The answer is surprisingly simple:
First, you want to break the char array into the "rows" of the CSV file. Depending on your line ending, you will choose one of these as a delimiter: \n, \r, or a combination of the two. For this example, we are using \n.
rows = split(array_o_chars, '\n');
Now that you have your rows, you need to create your columns, this is done in the same manner as your rows, except using , as your delimiter, or in this case , (a comma followed by a space).
cell_array = split(rows, ', ');
Now you have the 2d cell array you desire.
All together now:
% Test 1d array
array_o_chars = ['1' 'd' ',' ' ' 'a' 'r' 'r' 'a' 'y' '\n' 'o' 'f' ',' ' ' 'c' 'h' 'a' 'r' 's'];
% Conversion to cell array
rows = split(array_o_chars, '\n');
cell_array = split(rows, ', ');
% Show result in Command Window
display(cell_array);
Output from Matlab:
cell_array =
2×2 cell array
{'1d'} {'array'}
{'of'} {'chars'}
Can some one explain what this line here does? This is part of an old matlab code I need to reuse for my work
matdir = [params.ariens '-' num2str(dirtimes(ii))];
I'm especially confused about the '-' part. Thanks a lot in advance.
Single quotes are used to create a string literal so '-' simply creates a string containing the hyphen character. In MATLAB, [ ... ] performs horizontal concatenation so the line that you have shown concatenates the string stored in params.ariens, the character '-' and the number dirtimes(ii) converted to a string using num2str to creat one long string made up of those three strings.
For example:
c = ['abc', '-', 'def']
% abc-def
class(c)
% char
d = ['abc', '-', num2str(10)]
% abc-10
This is not exactly a question, because i have the answer, but as I couldn't find sources about it, i'll post the question along with the answer here in case it is of some interest for you. (And also to be able to find it again if i forget about how i did it).
I came across a problem while reviewing some code. The huge amount of variables were not explained in the code and everytime I wanted to know the meaning of a variable I had to look in the Data files and/or guess their meaning from the operations that were done in the code.
No need to say that this was pretty time consuming and i've searched the best way to lose less time.
First of all, I put all the explanations about the variables in comments, the problem being it's adding a (huge!) lot of lines in the script.
I'm also using the "Enable data tips in edit mode" in MATLAB. When you hover over a variable name MATLAB already evaluated, it gives you it's size along all dimensions and at least its first values, making it already easier to know what objects you are manipulating. (see image below)
The natural idea that came to my mind was the following : would it be possible to make MATLAB display some more custom informations in the data tips?
And the answer is yes!
See code in answer
We will need to do some preprocessing in order for this to work, i.e. :
1) Create a data file linking the variable names to their description
(This is the boring part, although i already had to do it in order to understand the code. Just add a line everytime you come across a new variable)
I chose to save these datas in a CSV file, where the first column contains the variable names and the second one contains the descriptions, e.g.
2) Edit MATLAB's function datatipinfo (It's inner code can be accessed by typing edit datatipinfo in MATLAB's command window)
The datatipinfo function looks like :
function datatipinfo(val)
% Some error checking / Initialization
function prefix=sizeType %#ok<DEFNU> All uses are in EVALC calls.
s = size(val);
D = numel(s);
if D == 2
theSize = [num2str(s(1)), 'x', num2str(s(2))];
elseif D == 3
theSize = [num2str(s(1)), 'x', num2str(s(2)), 'x', ...
num2str(s(3))];
else
theSize = [num2str(D) '-D'];
end
if isempty(val) == 0
prefix = [name ': ' theSize ' ' class(val)];
else
prefix = [name ': empty ' theSize ' ' class(val)];
end
end
% Some other stuff
end
And it's the prefix function that we'll edit in order to do what we want to do, along with some filescanning and string comparison in the initialization phase :
A) Initialization phase :
% Read data from csv file :
fid = fopen('ToyVars.csv');
Data = textscan(fid, '%s%s','whitespace','','delimiter',';');
fclose(fid);
B) Compare the name of the variable you're hovering on with the names of the variables in Data
NameFound=0;
% Get Variable Names and Corresponding comments
TmpNames=Data{1,1};
TmpComments=Data{1,2};
% Loop through TmpNames. If a Name matches, assign corresponding comment to the variable Comment
for ii=1:size(TmpNames,1)
if(isequal(char(TmpNames(ii))),name)
Comment=char(TmpComments(ii));
NameFound=1;
end
end
C) Add the comment in the datatip if NameFound==1
if NameFound
if isempty(val) == 0
prefix = [name ': ' theSize ' ' class(val) ' : ' Comment];
else
prefix = [name ': empty ' theSize ' ' class(val) ' : ' Comment];
end
else
if isempty(val) == 0
prefix = [name ': ' theSize ' ' class(val)];
else
prefix = [name ': empty ' theSize ' ' class(val) ];
end
end
And voilà!
With a slight tweak and some modifications to the calling function you can also utilize #BillBokeey's answer without any external dependencies. By placing a structure array in the same workspace as the variable you are previewing, you can store a string in a field with the same name as your variable and utilize evalin with the existing logic in datatipinfo to get the inputs for #BillBokeey's modifications.
For my test case I am storing my strings in a structure named mydatastrings:
mydatastrings.test = 'Test Variable';
In the body of datatipinfo I have added a try block:
NameFound = 0;
try
Comment = evalin('caller', sprintf('mydatastrings.%s', name));
NameFound = 1;
end
Along with #BillBokey's modifications to the nested prefix function:
if NameFound
if isempty(val) == 0
prefix = [name ': ' theSize ' ' class(val) ' : ' Comment];
else
prefix = [name ': empty ' theSize ' ' class(val) ' : ' Comment];
end
else
if isempty(val) == 0
prefix = [name ': ' theSize ' ' class(val)];
else
prefix = [name ': empty ' theSize ' ' class(val) ];
end
end
And we achieve the same results.
Full files are in this Gist
EDIT:
You can also make a minimal adjustment to datatipinfo to display a comment without modifying prefix. It seems like whatever executes datatipinfo also captures all of the outputs to the command window and displays them in the popup rather than the command window itself.
If we replace the previous try block with simply:
try
Comment = evalin('caller', sprintf('mydatastrings.%s', name))
end
And leave prefix as it is in the default MATLAB install, we obtain the following popup:
This is also included in the Gist as datatipinfo_noprefix.m
Another approach is to subclass a Matlab's already defined class such as double and add a string property. This string will appear on the data tip.
How to subclass with additional property:
http://fr.mathworks.com/help/matlab/matlab_oop/built-in-subclasses-with-properties.html
The result:
I'm trying to make an algorithm in Matlab that scans the character array from left to right and if it encounters a space, it should do nothing, but if it encounters 2 consecutive spaces, it should start printing the remaining quantities of array from next line. for example,
inpuut='a bc d';
after applying this algorithm, the final output should have to be:
a bc
d
but this algorithm is giving me the output as:
a bc
d d
Also, if someone has got a more simpler algorithm to do this task, do help me please :)
m=1; t=1;
inpuut='a bc d';
while(m<=(length(inpuut)))
if((inpuut(m)==' ')&&(inpuut(m+1)==' '))
n=m;
fprintf(inpuut(t:(n-1)));
fprintf('\n');
t=m+2;
end
fprintf(inpuut(t));
if(t<length(inpuut))
t=t+1;
elseif(t==length(inpuut))
t=t-1;
else
end
m=m+1;
end
fprintf('\n');
OK I gave up telling why your code doesn't work. This is a working one.
inpuut='a bc d ';
% remove trailing space
while (inpuut(end)==' ')
inpuut(end)=[];
end
str = regexp(inpuut, ' ', 'split');
for ii = 1:length(str)
fprintf('%s\n', str{ii});
end
regexp with 'split' option splits the string into a cell array, with delimiter defined in the matching expression.
fprintf is capable of handling complicated strings, much more than printing a single string.
You can remove the trailing space before printing, or do it inside the loop (check if the last cell is empty, but it's more costly).
You can use regexprep to replace two consecutive spaces by a line feed:
result_string = regexprep(inpuut, ' ', '\n');
If you need to remove trailing spaces: use this first:
result_string = regexprep(inpuut, ' $', '');
I have a solution without using regex, but I assumed you wanted to print on 2 lines maximum.
Example: with 'a b c hello':
a b
c hello
and not:
a b
c
hello
In any case, here is the code:
inpuut = 'a b c';
while(length(inpuut) > 2)
% Read the next 2 character
first2char = inpuut(1:2);
switch(first2char)
case ' ' % 2 white spaces
% we add a new line and print the rest of the input
fprintf('\n%s', inpuut(3:end));
inpuut = [];
otherwise % not 2 white spaces
% Just print one character
fprintf('%s', inpuut(1))
inpuut(1) = [];
end
end
fprintf('%s\n', inpuut);
I have a text file that looks like this:
(a (bee (cold down)))
if I load it using
c=textscan(fid,'%s');
I get this:
'(a'
'(bee'
'(cold'
'down)))'
What I would like to get is:
'('
'a'
'('
'bee'
'('
'cold'
'down'
')'
')'
')'
I know I can delimit with '(' and ')' by specifying 'Delimiter' in textscan, but then I will loose this character, which I want to keep.
Thank you in Advance.
The %s specifier indicates that you want Strings, what you want is individual chars. Use %c instead .
c=textscan(fid,'%c');
Update if you want too keep your words intact then you'll want to load your text using the %s specifier. After the text is loaded you can either solve this problem with Regular Expressions (not my forte) or write your own parser then parses each word individually and saves the paranthesis and words to a new cell array.
AFAIK, there is no canned routine capable of preserving arbitrary delimiters.
You'd have to do it yourself:
string = '(a (bee (cold down)))';
bo = string == '(';
bc = string == ')';
sp = string == ' ';
output = cell(nnz(bo|bc|sp)+1,1);
j = 1;
for ii = 1:numel(string)
if bo(ii)
output{j} = '(';
j = j + 1;
elseif bc(ii)
output{j} = ')';
j = j + 1;
elseif sp(ii)
j = j + 1;
else
output{j} = [output{j} string(ii)];
end
end
Which can probably be improved -- the growing character array will prevent the loop from being JIT'ed. The array bc | bo | sp holds all the information to vectorize this thing, I just don't see how at this hour...
Nevertheless, it should give you a place to start.
Matlab has a strtok function similar to C. Its format is:
token = strtok(str)
token = strtok(str, delimiter)
[token, remain] = strtok('str', ...)
there is also a string replace function strrep:
modifiedStr = strrep(origStr, oldSubstr, newSubstr)
What I would do is modify the original string with strrep to add in delimiters, then use strtok. Since you already scanned the string into c:
c = (c,'(','( '); %Add a space after each open paren
c = (c,')',' ) '); % Add a space before and after each close paren
token = zeros(10); preallocate for speed
i = 2;
[token(1), remain] = strtok(c, ' ');
while(remain)
[token(i), remain] = strtok(c, ' ');
i =i + 1;
end
gives you the linear token array of each of the string you requested.
strtok reference: http://www.mathworks.com/help/techdoc/ref/strtok.html
strrep reference: http://www.mathworks.com/help/techdoc/ref/strrep.html