i am learning the basics.In this basic simple, if a,b are call by reference then what is the result ?
10 25
10 25
or
10 25
10 15
Code :
function sub(int a, int b)
begin
print a,b;
end
function main
begin
int i := 10;
int j := 15;
sub(i,i+j);
print i,j;
end
10 25
10 15
In this case it makes no difference whether it's pass by reference or by value.
The Sub makes no changes to the variables, it just prints them.
Passing a variabile by reference means that inside the function you can change the variable value and outside you will have the value changed because you are passing to function its reference( the pointer to memory) and not its value. When you pass a variable by value the variable is copy inside the function so outside you have no effect
In you case the result will be
10 25
10 15
Related
I can find / identify all digits in a number using a recursive function.
My issue is trying to sum the number through each recursion.
I had to initialize sum = 0 at the top of my function statement, and when I return through recursion, I'm always resetting sum back to zero. I do not know how to save a variable without first initalizing it.
Code is below;
function output= digit_sum(input)
sum=0
if input < 10
output = input
else
y=rem(input,10);
sum=sum+y
z=floor(input/10);
digit_sum(z)
end
output=sum
end
I have two datasets that I want to merge together that have repeated by variables, but an unequal number of rows. In SAS, the default behavior is to retain values for all the rows that don't have a match.
For example:
data a;
input i x y;
datalines;
1 1 5
1 2 6
1 3 7
1 4 8
;
run;
data b;
input i f g $;
datalines;
1 9 aa
1 8 bb
;
run;
Here dataset a has four rows of the by variable i, while dataset b only has two.
Merging solely with the by variable i produces this:
data c;
merge a b;
by i;
run;
Obs i x y f g
1 1 1 5 9 aa
2 1 2 6 8 bb
3 1 3 7 8 bb
4 1 4 8 8 bb
You can see that for variables f and g in obs 3 and 4 the values have been retained since they didn't have a match in dataset a.
What I am trying to produce is this output:
Obs i x y f g
1 1 1 5 9 aa
2 1 2 6 8 bb
3 1 3 7 .
4 1 4 8 .
I am using SAS 9.4 and this is what I've tried:
data c;
if _n_>1 then do;
array num{*} _numeric_;
array char{*} _character_;
call missing(of num{*});
call missing(of char{*});
end;
merge a b;
by i;
run;
My thinking is that for every row after the first, I want to set all variables to missing and so that if they don't have a matching row their values won't be overwritten and will remain missing. This would eliminate retained values.
By the second row the PDV should be created and all the metadata should be available to create these arrays and set them to missing, but I am getting this error:
WARNING: Defining an array with zero elements.
Any suggestions on how to fix this code or other code that would do the trick?
You would want to override the default behavior of the run statement, namely the automatic output and automatic call missing of certain variables.
Here you output; to force the automatic output (same as default behavior) and then call missing(of _all_); which sets all variables to missing (as opposed to only ones not appearing on the merge or set statements).
data c;
merge a b;
by i;
output;
call missing(of _all_);
run;
The reason you have to do it at the end and not the beginning is that you haven't defined any variables yet at the beginning - so _numeric_, _character_, or _all_ don't have anything to refer to.
You can fix this, with an if 0 then set a b;, but I find the above solution a bit more straightforward. Really either works fine and has the same speed and benefit.
data c;
if 0 then set a b; *defines all of the variables, but `if 0` means it will not pull any data;
call missing(of _all_); *sets everything missing;
merge a b;
by i;
run;
Can anyone help me understand how to display the following pattern using a Progress 4gl frame:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5.
I have tried like this:
DEFINE VARIABLE a AS INTEGER NO-UNDO.
DEFINE VARIABLE b AS INTEGER NO-UNDO.
DO
a =1 TO 5 WITH FRAME f:
DO
b = 1 TO a WITH FRAME f:
DISPLAY a SPACE SKIP.
PAUSE.
END.
END.
/* while displaying the answer is overwritten, how do I display the answer side by side? */
If you were sending your output to a file you could do it like this:
define variable a as integer no-undo.
define variable b as integer no-undo.
output to "output.txt".
do a = 1 to 5:
do b = 1 to a:
put b.
end.
put skip.
end.
output close.
Using DISPLAY and FRAME is not like text files or printers. When you create a frame and DISPLAY "A" in it you are defining a single position where the variable will be displayed.
Every time that you DISPLAY A the value will be placed in the same position.
You can make it a DOWN frame and move to a new line with each iteration of the outer loop but you will still only have one position per line.
define variable a as integer no-undo.
define variable b as integer no-undo.
do a = 1 to 5 with frame f:
do b = 1 to a:
display b with frame f.
end.
down with frame f.
end.
To have multiple positions you need multiple variables or an array or you can build a string (doydoy44's solution). Here is an example with an array:
define variable a as integer no-undo.
define variable b as integer no-undo.
define variable c as integer no-undo extent 5 format ">>>>".
do a = 1 to 5 with frame f:
do b = 1 to a:
c[b] = b.
end.
display c with frame f.
down with frame f.
end
I'm not sur to understand what is the problem.
May be this can help you:
DEFINE VARIABLE a AS INTEGER NO-UNDO.
DEFINE VARIABLE b AS INTEGER NO-UNDO.
DEFINE VARIABLE woutput AS CHARACTER NO-UNDO.
DO
a =1 TO 5 WITH FRAME f:
woutput = "".
DO
b = 1 TO a WITH FRAME f:
woutput = woutput + " " + string(b).
END.
DISPLAY TRIM(woutput) SKIP .
PAUSE.
END.
The behaviour you are talking about is what I call a down frame. ABL creates a frame automatically for any output, and if you are displaying a series of records from a table, it knows to make that frame a down frame, for example:
for each customer no-lock:
display customer.
end.
But in your example you aren't using for each. To get the down frame behaviour you are going to have to make it happen yourself.
Here is the simplest code that will give you that:
def var v-i as int no-undo.
do v-i = 1 to 10 with down:
display v-i.
down.
end.
It's actually clearer what is going on, though, if you spell things out a bit further. Let's define a named frame, make it a down frame, and then use it:
def var v-i as int no-undo.
def frame f-x
v-i
with down.
do v-i = 1 to 10:
display v-i with frame f-x.
down with frame f-x.
end.
It's almost always worth defining a frame if you are outputting something, I find.
define variable a as int no-undo.
define variable b as int no-undo.
define variable res as char no-undo.
update a.
b = 1.
repeat while(b <= a):
res = res + " " + string (b).
b = b + 1.
disp res format "x(20)".
end.
In SAS/IML I try to pass to a user defined module a reference to a variable that is defined in macro. The module changes the variable value.
Since call of the function is in the do-loop I cannot use &-sign. However use of symget does not work. Here is my code.
proc iml;
start funcReference(argOut);
print "funcReference " argOut;
argOut = 5;
finish funcReference;
store module=funcReference;
quit;
proc IML;
mydata1 = {1 2 3};
call symput ('macVar', 'mydata1');
load module=funcReference;
run funcReference(symget('macVar'));
print mydata1;
quit;
The output shows that variable mydata1 have not changed:
argOut
funcReference mydata1
mydata1
1 2 3
Any ideas?
SOLVED
Thanks a lot!
You are sending in a temporary scalar matrix (the result of the SYMGET call). That temporary variable is being updated and promptly vanishes, as explained in the article "Oh, those pesky temporary variables!"
Instead of macro variables (which are text strings), you should use the VALUE and VALSET functions, as described in the article "Indirect assignment: How to create and use matrices named x1, x2,..., xn" You need to send in a real matrix in order for the values to be updated correctly, as follows:
proc IML;
load module=funcReference;
mydata1 = {1 2 3};
call symput('macVar', 'mydata1');
matrixName = symget('macVar'); /* matrix named &mydata1 */
z = value(matrixName); /* z contains data */
run funcReference(z); /* update values in z */
call valset(matrixName, z); /* update data in &mydata1 */
print mydata1;
I want to check the length of string got more than 20 characters, if more than 20 then will return 1 else return 0 in matrix form [n x 1]. But now, I get the answer of [1x1]. How do I modify my code in if-else statement to get the ans?
str = {'http://www.mathworks.com/matlabcentral/newsreader/view_thread/324182',
'http://jitkomut.lecturer.eng.chula.ac.th/matlab/text.html',
'http://www.ee.ic.ac.uk/pcheung/teaching/ee2_signals/Introduction%20to%20Matlab2.pdf'};
a = cellfun(#length,str)
if a > 20
'1'
else
'0'
end
Output:
a =
68
57
83
ans =
1
I want the output of, lets say
ans =
1
1
1
In Matlab, you can simply use (no if statement is needed):
a = cellfun(#length,str)
(a>20)'
This will give you:
a =
68 57 83
ans =
1
1
1
As #herohuyongtao mentions, you don't actually need an if, the if will only consider the first element of the matrix that it returns, hence giving you only a single value.
But you could actually do this all in your cellfun by using an anonymous function:
cellfun(#(x)(length(x) > 20), str)
And get the result in one shot.
As there is no equivalent of the c ternary operator (?:) in matlab, you can use the following two statements to replace your if then else statement, and achieve what you ask for:
b(a==a)='0'
b(a>20)='1'
The first line initializes the result array, where all value b defaults to the value of the else branch, i.e. '0',
the second line changes the elements for which the conditional > 20 holds to the value in the then branch, i.e. '1'.
If the output values are boolean, you can simply do:
(a>20)
as #herohuyongtao suggested or use #Dan's answer.