楼主: undifined
1116 4

[问答] &&name.&i.和&&name&i编译结果明显差异问题求教 [推广有奖]

  • 0关注
  • 0粉丝

高中生

45%

还不是VIP/贵宾

-

威望
0
论坛币
1828 个
通用积分
0
学术水平
0 点
热心指数
3 点
信用等级
0 点
经验
13948 点
帖子
19
精华
0
在线时间
17 小时
注册时间
2018-12-6
最后登录
2022-5-10

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
data text;
        set sashelp.class end=no_more;
        call symput('name',(trim(name)));
        if no_more then call symput('count',_N_);
        %put &name. &count.;
run;

%macro putloop;
        %local i;
        %do i=1 %to &count.;
                %put name&i. is &&name&i;
        %end;
%mend;
%putloop;

运行如上代码,结果正确,日志如下:

威廉           19

NOTE: 数值已转换为字符值,位置:(行:列)。
      96:41
NOTE: 从数据集 SASHELP.CLASS. 读取了 19 个观测
NOTE: 数据集 WORK.TEXT 有 19 个观测和 5 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.02 秒
      CPU 时间          0.01 秒


NOTE: 宏 PUTLOOP 完成编译,没有错误,
      11 条指令,188 个字节。
name1 is 阿尔弗雷德
name2 is 爱丽丝
name3 is 芭芭拉
name4 is 凯露
name5 is 亨利
name6 is 詹姆斯
name7 is 简
name8 is 雅妮特
name9 is aaa
name10 is 约翰
name11 is 乔伊斯
name12 is 茱迪
name13 is 罗伊斯
name14 is 玛丽
name15 is 菲利普
name16 is 罗伯特
name17 is 罗纳德
name18 is 托马斯
name19 is 威廉


将代码中%put name&i. is &&name&i;改为%put name&i. is &&name.&i.;
结果错误,日志如下:

威廉           19

NOTE: 数值已转换为字符值,位置:(行:列)。
      124:41
NOTE: 从数据集 SASHELP.CLASS. 读取了 19 个观测
NOTE: 数据集 WORK.TEXT 有 19 个观测和 5 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.02 秒
      CPU 时间          0.01 秒


NOTE: 宏 PUTLOOP 完成编译,没有错误,
      11 条指令,192 个字节。
name1 is 威廉1
name2 is 威廉2
name3 is 威廉3
name4 is 威廉4
name5 is 威廉5
name6 is 威廉6
name7 is 威廉7
name8 is 威廉8
name9 is 威廉9
name10 is 威廉10
name11 is 威廉11
name12 is 威廉12
name13 is 威廉13
name14 is 威廉14
name15 is 威廉15
name16 is 威廉16
name17 is 威廉17
name18 is 威廉18
name19 is 威廉19


&&name.&i.和&&name&i在编译和执行中有什么区别?还是其他的原因导致第二次结果错误?




二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:阿尔弗雷德 处理时间 二次结果 数据集 菲利普 sas

沙发
steven_1017 发表于 2019-4-14 01:33:27 |只看作者 |坛友微信交流群
楼主好,你第一段程序按说就不会得到正确结果,因为call symput定义的macro参数,在data step的每一个iteration中都会被新的name的值覆盖,最后整个test的data step运行完毕后,你得到的只能是“威廉”这个value,不可能出现整个name的listing。
第一段程序修改如下:
  1.         set sashelp.class end=no_more;
  2.         call symput('name'||left(put(_n_,3.)),(trim(name)));
  3.         if no_more then call symput('count',_N_);
  4. run;

  5. %put &name. &count.;
  6. %put _user_;

  7. %macro putloop;
  8.         %local i;
  9.         %do i=1 %to &count.;
  10.                 %put name&i. is &&name&i;
  11.         %end;
  12. %mend;
  13. %putloop;
复制代码


就可以得到正确的结果了,因为每一个iteration都会给不同的macro variable赋值,不会覆盖同一个variable下面的值。

关于&&name.&i与&&name&i在宏编译阶段是有区别的:对于&&name.&i,宏编译过程中,先把&&合并为一个&,然后把&i解析出来,变成&name.2(假设i=2),然后再对&name.进行解析。假如&name的值是“威廉”,那么解析出来的结果就是威廉2。而对于&&name&i,在编译过程中,先变为&name2,此刻再解析的时候,可就不是解析&name,而是解析名字为name2的macro。本人也是通过这种方式给name1, name2, ....name19这19个不同的macro variables赋予了不同的值,来达到你所期望的结果的。

希望以上解释能够回答你的问题。
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
admin_kefu + 30 + 2 + 2 + 2 热心帮助其他会员

总评分: 论坛币 + 30  学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

使用道具

藤椅
undifined 发表于 2019-4-14 07:35:01 |只看作者 |坛友微信交流群
steven_1017 发表于 2019-4-14 01:33
楼主好,你第一段程序按说就不会得到正确结果,因为call symput定义的macro参数,在data step的每一个itera ...
谢谢你详细的回答~
有几个地方不必太清楚,麻烦请教下~
1、call symput生成了name、namen共20个宏变量,为什么会有name?
2、生成的name、namen是全局宏变量,为什么不是局部宏变量?
3、%put _user_;日志中的顺序如下(只截取部分),为什么不是name1-name19,或者name19-name1,sas在Symbol Tables中存储是乱序的吗?
GLOBAL COUNT           19
GLOBAL NAME 威廉
GLOBAL NAME1 阿尔弗雷德
GLOBAL NAME10 约翰
GLOBAL NAME11 乔伊斯
GLOBAL NAME12 茱迪
GLOBAL NAME13 罗伊斯
GLOBAL NAME14 玛丽
GLOBAL NAME15 菲利普
GLOBAL NAME16 罗伯特
GLOBAL NAME17 罗纳德
GLOBAL NAME18 托马斯
GLOBAL NAME19 威廉
GLOBAL NAME2 爱丽丝

使用道具

板凳
steven_1017 发表于 2019-4-15 09:15:45 |只看作者 |坛友微信交流群
undifined 发表于 2019-4-14 07:35
谢谢你详细的回答~
有几个地方不必太清楚,麻烦请教下~
1、call symput生成了name、namen共20个宏 ...
有Name这个macro,是因为之前你的第一段程序运行后产生的macro variable,只要你还没有离开这个SAS session,它会一直在。
用data step调用call symput肯定产生的时候全局变量,即使是在macro definition中,假如带有data step调用call symput产生的macro,也是全局变量。有且只有在全局变量没有同名的macro name,或者在macro definition的arguments中带有的macro name,才是局部macro 变量,或者采用local予以强制。

%put _user_对于这个数字的排序,应该是1 10 11 12......2 20 21 22......3 30 31 32

使用道具

报纸
undifined 发表于 2019-4-23 23:22:06 |只看作者 |坛友微信交流群
steven_1017 发表于 2019-4-15 09:15
有Name这个macro,是因为之前你的第一段程序运行后产生的macro variable,只要你还没有离开这个SAS sessi ...
明白 O(∩_∩)O谢谢

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-24 21:00