Please help: Cell contents assignment to a non-cell array object.
4 次查看(过去 30 天)
显示 更早的评论
This is the error message/output:
num2word(1234)
nDigits =
1 2 3 4
Cell contents assignment to a non-cell array object.
Error in num2word (line 178) wordArray{i} = 'Two Hundred';
I originally wrote this for just numbers 1 through 9 and it worked perfectly, it was only after I made it work for up to a million that it stopped working and all I did was basically copy paste my original switch and then add if conditionals.
Here is my code.....
function [wordArray] = num2word(num)
nDigits = dec2base(num,10) - '0' wordArray = [' ':length(nDigits):' ']; wordArray = cellstr(wordArray); %wordArray = cell(1,20); tried this but no..
%these variables are switches, one the of statement containing them is ran %they change values meaning that the switch has been turned off a = 0; b = 0; c = 0; d = 0; e = 0; f = 0; for i=1:(length(nDigits)) %millions if length(nDigits) >= 7 && i == 1
switch nDigits(i) case 0 wordArray{i} = ' '; case 1 wordArray{i} = 'One Million'; case 2 wordArray{i} = 'Two Million'; case 3 wordArray{i} = 'Three Million'; case 4 wordArray{i} = 'Four Million'; case 5 wordArray{i} = 'Five Million'; case 6 wordArray{i} = 'Six Million'; case 7 wordArray{i} = 'Seven Million'; case 8 wordArray{i} = 'Eight Million'; case 9 wordArray{i} = 'Nine Million'; end
%hundred thousands elseif length(nDigits) >= 6 && a == 0 a = 1; switch nDigits(i) case 0 wordArray{i} = ' '; case 1 wordArray{i} = 'One Hundred and'; case 2 wordArray{i} = 'Two Hundred and'; case 3 wordArray{i} = 'Three Hundred and'; case 4 wordArray{i} = 'Four Hundred and'; case 5 wordArray{i} = 'Five Hundred and'; case 6 wordArray{i} = 'Six Hundred and'; case 7 wordArray{i} = 'Seven Hundred and'; case 8 wordArray{i} = 'Eight Hundred and'; case 9 wordArray{i} = 'Nine Hundred and'; end
% Ten thousands elseif length(nDigits) >= 5 && b ==0; b = 1; switch nDigits(i) case 0 wordArray{i} = ' '; case 1 % if wordArray{i+1} > 0 (teens); the c variable is so that % we can leave the next cell blank '' switch nDigits(i+1) case 0 wordArray{i} = 'Ten Thousand'; c = 2; case 1 wordArray{i} = 'Eleven Thousand'; c = 2; case 2 wordArray{i} = 'Twelve Thousand'; c = 2; case 3 wordArray{i} = 'Thirteen Thousand'; c = 2; case 4 wordArray{i} = 'Fourteen Thousand'; c = 2; case 5 wordArray{i} = 'Fifteen Thousand'; c = 2; case 6 wordArray{i} = 'Sixteen Thousand'; c = 2; case 7 wordArray{i} = 'Seventeen Thousand'; c = 2; case 8 wordArray{i} = 'Eighteen Thousand'; c = 2; case 9 wordArray{i} = 'Nineteen Thousand'; c = 2; end case 2 wordArray{i} = 'Twenty '; case 3 wordArray{i} = 'Thrirty '; case 4 wordArray{i} = 'Fourty '; case 5 wordArray{i} = 'Fivty '; case 6 wordArray{i} = 'Sixty '; case 7 wordArray{i} = 'Seventy '; case 8 wordArray{i} = 'Eighty '; case 9 wordArray{i} = 'Ninety '; end
% Ten thousands elseif length(nDigits) >= 4 && c ==0; c = 1; switch nDigits(i) case 0 wordArray{i} = ' '; case 1 wordArray{i} = 'One'; case 2 wordArray{i} = 'Two Thousand'; case 3 wordArray{i} = 'Three Thousand'; case 4 wordArray{i} = 'Four Thousand'; case 5 wordArray{i} = 'Five Thousand'; case 6 wordArray{i} = 'Six Thousand'; case 7 wordArray{i} = 'Seven Thousand'; case 8 wordArray{i} = 'Eight Thousand'; case 9 wordArray{i} = 'Nine Thousand'; end
% Ten thousands for teens elseif length(nDigits) >= 4 && c ==2; c = 1; wordArray{i} = '';
% Hundreds elseif length(nDigits) >= 3 && d ==0; d = 1; switch nDigits(i) case 0 wordArray{i} = ' '; case 1 wordArray{i} = 'One Hundred'; case 2 wordArray{i} = 'Two Hundred'; case 3 wordArray{i} = 'Three Hundred'; case 4 wordArray{i} = 'Four Hundred'; case 5 wordArray{i} = 'Five Hundred'; case 6 wordArray{i} = 'Six Hundred'; case 7 wordArray{i} = 'Seven Hundred'; case 8 wordArray{i} = 'Eight Hundred'; case 9 wordArray{i} = 'Nine Hundred'; end
elseif length(nDigits) >= 2 && e ==0; e = 1; switch nDigits(i) case 1 % if wordArray{i+1} > 0 (teens); the f variable is so that % we can leave the next cell blank '' switch nDigits(i+1) case 0 wordArray{i} = 'Ten '; f = 2; case 1 wordArray{i} = 'Eleven '; f = 2; case 2 wordArray{i} = 'Twelve '; f = 2; case 3 wordArray{i} = 'Thirteen '; f = 2; case 4 wordArray{i} = 'Fourteen '; f = 2; case 5 wordArray{i} = 'Fifteen '; f = 2; case 6 wordArray{i} = 'Sixteen '; f = 2; case 7 wordArray{i} = 'Seventeen '; f = 2; case 8 wordArray{i} = 'Eighteen '; f = 2; case 9 wordArray{i} = 'Nineteen '; f = 2; end case 2 wordArray{i} = 'Twenty '; case 3 wordArray{i} = 'Thrirty '; case 4 wordArray{i} = 'Fourty '; case 5 wordArray{i} = 'Fivty '; case 6 wordArray{i} = 'Sixty '; case 7 wordArray{i} = 'Seventy '; case 8 wordArray{i} = 'Eighty '; case 9 wordArray{i} = 'Ninety '; end
elseif length(nDigits) >= 1 && f ==0; f = 1; switch nDigits(i) case 0 wordArray{i} = ''; case 1 wordArray{i} = 'one'; case 2 wordArray{i} = 'two'; case 3 wordArray{i} = 'three'; case 4 wordArray{i} = 'four'; case 5 wordArray{i} = 'five'; case 6 wordArray{i} = 'six'; case 7 wordArray{i} = 'seven'; case 8 wordArray{i} = 'eight'; case 9 wordArray{i} = 'nine'; end
% double digits for teens elseif length(nDigits) >= 4 && f ==2; f = 1; wordArray{i} = ''; end
wordArray = strjoin(wordArray);
end end
If you actually read all of this then you are a boss. I am sure that there is a more efficient way to do this; I am just starting with matlab.
2 个评论
Stephen23
2016-11-24
@David Davis: if you want to check the output of your function, then you can compare with the output of my FEX submission:
I wrote my code to take into account many edge cases (arising from grammatical rules and from the limits of numeric calculations). My code was also tested on thousands of test cases, collected from online sources and other references.
回答(2 个)
Image Analyst
2016-11-24
Get rid of
wordArray = [' ':length(nDigits):' '];
wordArray = cellstr(wordArray);
Use this:
wordArray = cell(1,20);
And at the bottom of the function get rid of
wordArray = strjoin(wordArray);
and have this instead:
w = wordArray{:}
It will run without error, though it gives you the wrong answer still. I assume you can figure it out after that though.
2 个评论
Guillaume
2016-11-24
Yes, wordArray = [' ':length(nDigits):' ']; doesn't work. I assume it's meant to be wordArray = repmat(' ', numel(nDigits)); but as ImageAnalyst says, wordArray cell(1, 20) is a much simpler way of creating a cell array.
However, wordArray = strjoin(wordArray) is perfectly fine, and w = wordArray{:} will error. I assume IA meant w = [wordArray{:}] but unlike strjoin it won't put a space between each string.
Guillaume
2016-11-24
I don't understand the purpose of the extremely badly named a, b, ... f. Use meaningful variable names.
In any case, the best way for you to find what is going wrong is to use the debugger. Step through your program step by step and see if it does what you expected it to do. You'll quickly see where it goes wrong.
One thing I must say, seeing all these switch ... case fills me with horror. How about using array indexing instead:
digitwords = {'one', 'two', 'three', 'four', five', 'six', 'seven', 'eight', nine'}
wordArray{i} = digitwords(ndigits(i));
These two lines replace a whole switch ndgits{i} ... case ... case ... end
I would also work backwards from the units up to the first digit.
3 个评论
Stephen23
2016-11-25
编辑:Stephen23
2016-11-26
@David Davis: if you want to see one way of solving this task, see my function (which does exactly what you are trying to do). Note that my code has been extensively tested, and works correctly with many edge cases.
After much experimetnation and thought on how to achieve this, I ended up using MATLAB's ability to work with arrays, rather than using slower loops. In a nutshell: put the digits into a numeric matrix arranged by hundreds, tens, and ones, and then use this to index the correct text.
Guillaume
2016-11-25
Having thought about it a bit more, I wouldn't have a loop over the digits. Instead I would separate the digits in groups of three (starting from the end). For each group of three, I would call either the same function or a subfunction that would create the word string and when it returns append either the million, thousand or nothing. So it would look something like this:
function wordstring = num2word(number)
%example number = 1,234,567,890
split number into group of three. e.g. {1, 234, 567, 890}
reverse group order {890, 567, 234, 1}
thousands = {'', 'thousand', 'million', 'milliard'}; %using long-notation https://en.wikipedia.org/wiki/Long_and_short_scales
for groupidx = 1 : numel(group)
call subfunction(group{groupidx})
append thousands{groupidx}
end
end
function wordstring = subfunction(number)
%number is guaranteed to be less than 1000
ones = {'', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'};
teens = {'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'};
tens = {'', '', 'ERROR', 'Twenty', 'Thirty', 'Fourty', 'Fifty', 'Sixty', 'Seventy', 'Eigthy', 'Ninety'};
decades = mod(number, 100);
if decades >= 10 && decades < 20
wordstring = teens(decades-9);
else
wordstring = strtrim(strjoin(tens{floor(decade / 10), ones(mod(decade, 10))));
end
if number >= 100
wordstring = strjoin(floor(number / 100), 'hundred', wordstring)
end
end
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Data Import and Analysis 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!