How to request additional data from the user in a function
2 views (last 30 days)
Show older comments
Hi, Thanks for reading this.
I have to call a function, then it appears I need to request more data from within the function. Data the user is supposed to type on the screen. How do I do this? The problem is stated as:
I have to admit I'm a little unclear with regard to what the problem statement is requesting.
11 Comments
Stephen23
on 10 May 2018
@Lauren Jablonowski: none of your for loops make any sense. Get rid of them. Use one if statement.
Lauren Jablonowski
on 18 May 2018
@Stephen Cobeldick: thanks! with the if statement and isscalar function I was able to fully solve this.
Accepted Answer
Stephen23
on 8 Dec 2016
Edited: Stephen23
on 8 Dec 2016
Something like this:
function out = year2016(m)
VN = datenum([2016,m,1]):datenum([2016,m+1,1])-1;
DN = 1+mod(VN-3,7);
MC = {'January';'February';'March';'April';'May';'June';'July';'August';'September';'October';'November';'December'};
DC = {'Mon','Tue','Wed','Thu','Fri','Sat','Sun'};
out = struct('day',DC(DN),'date',num2cell(1:numel(VN)));
[out(:).month] = deal(MC{m});
end
And tested:
>> m = year2016(12); m(8)
ans =
day = Thu
date = 8
month = December
>> m = year2016(1); m(1)
ans =
day = Fri
date = 1
month = January
>> m = year2016(2); m(29)
ans =
day = Mon
date = 29
month = February
3 Comments
Stephen23
on 8 Dec 2016
Edited: Stephen23
on 8 Dec 2016
@DJ V: I used datenum and colon notation to generate a vector of all serial date numbers for the selected month. Then mod to determine the day of the week as an index from 1 to 7. The day field is generated using this index to select the day of the week from a cell array of strings. The date field is generated by simply generating a vector of numbers from 1 to the length of the day field. The month field is simply filled in by using the input month to select the month string from a cell array of strings.
Here are the first two critical lines:
>> m = 2; % feb
>> VN = datenum([2016,m,1]):datenum([2016,m+1,1])-1
VN =
736361 736362 736363 736364 736365 736366 736367 736368 736369 736370 736371 736372 736373 736374 736375 736376 736377 736378 736379 736380 736381 736382 736383 736384 736385 736386 736387 736388 736389
>> DN = 1+mod(VN-3,7)
DN =
1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1
DN is a vector of all days of the week for the month. Check it yourself if you do not believe me (Hint: the first and last days of February 2016 were both Mondays, which is what my code shows above). This vector DN is simply used as an index to give the days corresponding to the dates, exactly as requested. The dates is a simple vector from 1 to numel(..) because where I come from the first day of the month is the 1st.
"I don't see how this will make the days of the month correspond to the dates"
That is okay. Use MATLAB's documentation to help you understand how the functions I used work. Try them out yourself: play around with them, try different values. When you do this you might learn some much better ways to write code than relying on if's and copy-and-pasting hundreds of lines of text.
More Answers (3)
Geoff Hayes
on 7 Dec 2016
DJ - the function returns an array of structs where each element corresponds to a day of the month. So if the user passes in an integer that is outside of the interval [1,12], then an empty array is returned. If the integer is within this interval, then the array has that many structs as days in the month. For example, if 1 is the passed in integer, then the output is an array of 31 elements where m(1) corresponds to January 1rst, m(2) corresponds to January 2nd, etc.
Walter Roberson
on 7 Dec 2016
Your code uses (for example)
for n = 1 :31
datevalue(n) =n;
monthvalue(n)='August';
end
assigns numeric values to datevalue, so datevalue(1) is a numeric scalar.
Then after that you
dayvalue(1)='Mon';
or similar. That attempts to assign the 3-element character vector ['M', 'o', 'n'] to the single numeric scalar position dayvalue(1)
In order to be able to make the assignment
dayvalue(1)='Mon';
you would need to modify your initialization loop to
for n = 1 :31
datevalue(n) = strings(1);
monthvalue(n)='August';
end
(there are other better ways, but this is the minimum change.)
You will need to be using R2016b to do this. If you are using any earlier release then it is not possible to do
dayvalue(1)='Mon';
and you would need to switch to cell arrays such as
dayvalue{1}='Mon';
after having change the initialization to
for n = 1 :31
datevalue(n) = cell(1);
monthvalue(n)='August';
end
(again, there are better ways.)
6 Comments
Radoslav Gagov
on 10 Apr 2017
Here is how I dealed with the Problem:
m = year2016(n)
if length(n) ~= 1 || n < 1 || n >12 || n ~= round(n)
year = []; m = year;
else
year = [];
a{1} = 'Mon'; a{2} = 'Tue'; a{3} = 'Wed'; a{4} = 'Thu';
a{5} = 'Fri'; a{6} = 'Sat'; a{7} = 'Sun';a{8} = 'Mon';
a{9} = 'Tue'; a{10} = 'Wed'; a{11} = 'Thu';
a{12} = 'Fri'; a{13} = 'Sat'; a{14} = 'Sun';
if n == 1 || n == 3 || n==5 || n==7 || n==8 || n==10 ||
n==12
for i = 1 : 31
p = mod(i,7) ;
if p == 0
p = 7;
end
year(1).m(i).month = 'January';
year(1).m(i).date = i;
year(1).m(i).day = a{p+4};
year(3).m(i).month = 'March';
year(3).m(i).date = i;
year(3).m(i).day = a{p+1};
year(5).m(i).month = 'May';
year(5).m(i).date = i;
year(5).m(i).day = a{p+6};
year(7).m(i).month = 'July';
year(7).m(i).date = i;
year(7).m(i).day = a{p+4};
year(8).m(i).month = 'August';
year(8).m(i).date = i;
year(8).m(i).day = a{p};
year(10).m(i).month = 'October';
year(10).m(i).date = i;
year(10).m(i).day = a{p+5};
year(12).m(i).month = 'December';
year(12).m(i).date = i;
year(12).m(i).day = a{p+3};
end
end
if n == 4 || n == 6 || n==9 || n==11
for i = 1 : 30
p = mod(i,7) ;
if p == 0
p = 7;
end
year(4).m(i).month = 'April';
year(4).m(i).date = i;
year(4).m(i).day = a{p+4};
year(6).m(i).month = 'June';
year(6).m(i).date = i;
year(6).m(i).day = a{p+2};
year(9).m(i).month = 'September';
year(9).m(i).date = i;
year(9).m(i).day = a{p+3};
year(11).m(i).month = 'November';
year(11).m(i).date = i;
year(11).m(i).day = a{p+1};
end
end
if n == 2
for i = 1 : 29
p = mod(i,7) ;
if p == 0
p = 7;
end
year(2).m(i).month = 'February';
year(2).m(i).date = i;
year(2).m(i).day = a{p};
end
end
m = year(n).m;
end
end
1 Comment
Stephen23
on 10 Apr 2017
Edited: Stephen23
on 10 Apr 2017
Some observations:
- This code is much more complicated than it needs to be. More code -> harder to check and more bugs.
- Do not write code that already exists and does what you need, particularly when it is tested and more optimized than what you can write yourself. The date functions datenum, etc, already convert and give the correct date/day values, so there is no point in replicating this using loops, etc.
- This code generates multiple months, even though only one of them is output. Not an efficient use of memory.
- Uses loops, and expands the structures on each loop iteration. Not an efficient use of memory.
- Uses magic numbers (these are the days per month): code should not use magic numbers without adequate explanation.
- Defines a in a very strange way. Much simpler: a = {'Mon','Tue',...}.
- Uses more than fourteen times as many lines of code as my answer.
- Is nearly thirty times slower than my answer (1000 repetitions):
Elapsed time is 1.26207 seconds. % my answer
Elapsed time is 34.606 seconds. % this answer
Hopefully other beginners will not use this as an example to learn MATLAB from.
See Also
Categories
Find more on Dates and Time 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!