漠丶涯

吃鸡( ̄∇ ̄)

计算机专业要不要考研——写的很棒

你说:“他们都有很强的开发能力,只是不太喜欢读书,也只是希望混个学历对今后在岗位上晋升有好处”,我可以向你保证,你所说的人绝对不是开发能力很强的人。因为,1)高手不可能不喜欢读书;2)高手不可能想去混一个学历;3)高手不可能认为晋升是因为学历的原因。 
   
  还需要说明的是,考计算机的人未必个个都是高手,严格来说,大部分都不会编程序。也就是说,庸庸碌碌之辈仍然占绝大多数。研究生毕业的师兄只拿2500元左右的比比皆是,所以不要寄希望于拿一张研究生文凭出去赚高薪。但是,对于有实际开发工作经验的人,要想自己在3年之中有一个真正的提高的话,计算机学院提供了广阔的平台。就我所知,每一个月拿2万以上的也有(上海育碧,图形特效算法设计)。所以,同为研究生毕业,能力的差距是极大的。所以,不要去问“研究生毕业能拿多少?”,要问“像我这种水平的人,研究生毕业能拿多少钱?”这样人家才能够准确地回答你。 
   
  所谓“有实际开发工作经验”是指你目前已经具备下列能力:1)你已经认为C++汇编语言都是很简单的语言,并能够自如地运用;2)你能够在30分钟之内想到正确的五子棋 AI算法设计思路和方向;3)你完全理解STL为什么这么重要;4)你能够独立地解决所有的编译与链接问题,哪怕你从来没有遇到的问题,你也不需要询问任何人;5)英文网站是你的首要信息来源;6)能够读懂英语写成的国际标准,比如NTFS磁盘格式标准。7)你经常站在集合论的角度思考算法问题;8)能够理解一个简单的驱动程序,能够理解一个简单3D交互程序;9)你能够认识到线性代数和概率论在实际编程工作中的极端重要性;10)你完全理解COM的设计思想,尤其能够理解COM为什么要设计成这样;11)当我说到虚函数的重要作用时,你不会急着去找书来翻;12)你能够说出C++为什么比其他语言优秀的理由,记住这种理由应该来自于你的开发体会,而不是因为其他人都这么说。此外还有很多判断标准,但如果你同时具备5条以上,可以认为你已经具备相应的开发经验了。在这种状态下读研,你将取得读研效益的最大值。   
 读研最重要的是要明白你自己要干什么,不能等导师来告诉你你应该干什么。研究生的优势在于理论功底深厚,思维具有穿透力,当然编程能力首先要过关,不要读完研究生还不知道MFC程序的WinMain函数在哪里。所以,研究生期间,你一定要做有理论深度的算法设计,比如大规模数据的搜索算法,性能是首要考虑因素,不要奢望SQL函数能够帮你解决问题,所有的问题你都必须自己解决,你必须解决内外存交换的性能瓶颈。再比如极品飞车的3D场景生成,图形变换,碰撞检测,物性模拟,纹理映射,灯光模型等等,这些都是可以保证你能拿到2万以上月薪的技术。如果你认为这些东西太难,不可能做得出来的话,那么你就不适合读研。真的,要是你认为读研之后还是要去搞一般的程序设计,如信息管理系统之类的软件,那么你读研的价值就完全不会得到体现,因为这些工作根本就不需要读研。

 1)关于读书的机会成本问题。读研的机会成本的确是很高。任何人都可以简单地计算出来。所以,我也不赞成所有的人都去读研。读研只适合那些痛感数学在编程中的极端重要性的人。如果对理论工具和理论思维的极端重要性没有切肤的认识,那么读研的价值几乎为0;读研的好处在于:A,把你自己放在一个学术和工程的交叉点上;B,让你具备了进入微软等世界顶级软件研发机构的可能性;记住只是可能性。但是不读研这种可能性为0;C,如前所述,如果没有读研的机会,你也就没有静下心来好好钻研几年理论的机会;一边工作拿高薪,一边深入地学习各种理论,诸位认为这可能吗?我反正认为不可能,我觉得学习钻研理论最需要的就是一个长期安静独处的环境,一边工作一边读书是不可能有这样的环境的,你会觉得每天都在疲于奔命。而读研正好可以提供这样一个环境。我同时还反对整天跟着导师的屁股后面跑,这样会浪费很多时间。读计算机的研究生,主要依靠自己去查阅最新文献,自己去研读文献,和导师的口头交流一个月一次就足够了,前提还需要导师的水平足够牛。如果导师的水平不牛,这也没关系,不理他就是了,自己做好自己的事情即可。 
   
  2)关于研究生教学质量问题。坦白地说,全国都是“洪桐县中无好人”,尤其在计算科学领域,大牛极少。那为什么还要去读研?大哉问!把读研的收获寄托在名校或名师的名我认为气上,是注定要失败的。读研全靠自学,研究生之间的差距全部体现在自学能力上面。又有人问,既然是自学,为什么非要读研?回答是:因为读研就是为你买一份保险,就是买一份你自学三年之后不会失业的保险。这份保险主要是一种心理上的后盾,让你在自学过程中经得起诱惑,能够从容镇定地去追寻计算机理论发展的坚实足迹,从欧拉,费马,高斯,康托,图灵等巨匠那里寻找方法论的珠宝。倘若没有这份保证,你在家里面自学3个月,保证你会被失业的压力压得喘不过气来,何谈安心学习? 
   
  3)关于实战经验与理论学习的优劣问题。这没有定论,如前所述,管理信息系统,设备驱动开发,工具软件开发,软件病毒剖析等等这些工作不太需要创造性,需要的是耐心和经验,需要的是对既有规范的准确理解,这类开发工作最适合在实战中提高,理论学习没什么作用。但是在人工智能,模式识别,图像压缩,虚拟现实,巨量数据检索,自然语言理解,计算机图形学等等领域,理论熬驼季葑啪 缘耐持蔚匚唬≌庑┝煊虻耐黄贫匀死嗟纳 畹挠跋焓羌 渚薮蠖 羁痰摹D承┝煊虼τ谝桓黾 淇焖俜⒄沟奶 浦 校 热缂扑慊 夹窝В 嘈胖罹芄淮又诙?D游戏的灿烂辉煌中体认到我的这种说法。在这些领域,如果没有扎实的理论功底,一切都是那么遥远,不管你花了多少时间在编程上面。 
   
  4)关于高级研发人员的知识结构问题。首先声明,我不是一个纯粹理论激进分子,即认为除了理论之外,一切都不重要。我认为,纯熟的编程技能是最基本但也是最必不可少的技能。没有这个基础,一切计算机理论就是空谈(研究图灵可计算性理论的研究者除外)。有了这个基础之后,下列理论学习方向必须重点突破: 
   
  1,科学哲学。这是核心中的核心!可惜国内不开这门课。不但不开课,而且还作为批判对象来引用,实在是遗憾至极!这是一门教你如何“钓鱼”的学科,在一切科学研究中居于最核心的地位。它是古今科研方法和思维方法的集大成者,很难想象一个成熟的研究者没有一套自己的方法论体系。科学哲学最需要的是领会与总结,它的思想与启示会伴随我们的一生。 
   
  2,康托集合论,矩阵方法,离散结构,图论方法,群论方法之间的紧密关系。最重要的认识这些理论对实践的重要启示和方法引导。我始终认为,如果你学了一门理论之后,却不知道这门理论有什么作用,那么你的理论就白学了,你什么东西都没有捞着。所以,学习任何理论之前,先问自己:它有什么用?在哪里用?如何用?带着这些问题去学习理论,你才会真正地学到东西。用这三个问题去问你的理论课老师,他的回答就是判断其实际水平的最佳标准
   
  3,思维要有极强的穿透力,学会看透文献作者没有写出来的动机。绝大部分大师都有隐瞒自己最具有方法论启示意义的思考环节的习惯。牛顿和华罗庚先生都有这个坏习惯。这让大家认为他们是天才,因为很多问题他想到了,我们想不到。但是为什么他们能想到,我们想不到?他们是怎样想到的?没有人告诉我们牛顿发现万有引力定律时的思考过程,当然,牛顿可以慷慨地把他的思考结果告诉我们,但是,他那可以点石成金的“金手指”却没有教给我们。我们的任务就是要培养透过文章看穿作者背后意图和动机的能力,在这方面,台湾的侯捷和美国的 Donbox是绝佳典范。这两只老狐狸(呵呵,是爱称)凭着其猎犬一般的嗅觉,抽丝剥茧,一个把COM背后的幕后设计动机揭开并暴露到了光天化日之下,另一个把MFC的宏观架构做了一次完美的外科手术。其非凡的思维穿透力令人惊叹。

 4,英语。英语本身不重要,但是用英语写成的文献就极其重要了。所以,专门把英语作为一个重头戏列出来。大家不要相信英语无用论的鬼话。对于搞计算机的而言,英语就是你的母语! 
   
  5,其它的具体理论还有很多,但是都不如这三个方面重要,因为我觉得这三个方面是最具有根本性,全局性的能力培养环节。需要指出的是,很多高深理论对你的工作是无意义的,当心时间陷进去。一定要把效率最高的时间段用在最具有决定性意义的理论学习上。 
   
  5)关于读研之后的出路是否光明的问题。我们应该承认,读研之后,你的工作机会不是变多了,而是变少了。而且越是高手,他的工作机会和工作范围就越少。这是因为,越是搞前沿研发的公司,其数量越少,在这个圈子的人也就越少。你找工作的范围就越小,试问:如果微软的OS设计专家出来找工作,能够让他选择的公司能有几家?但是,这种公司数量的减少是以工资待遇的急剧上升为补偿的,同时,你在工作中所受到的充分尊重也是在一般公司中体会不到的。所以不要担心学了高科技用不上,呵呵,你只会越来越感觉自己学的不够用。相信接到过猎头公司电话的人会体会得到。真正的高手从来就不会担心工作的问题,也从来不会到人才市场上去找工作。既然选择了理论深入,那么就应该把眼光放得更远。


ABAP三类内表:标准表,排序表和哈希表

  ABAP中有三类内表,标准表,排序表和哈希表。

三种内表介绍

   标准表的每一行对应一个逻辑索引-SY-TABIX,填充内表的时候,可以将数据附加在现有行

之后,也可以插入到指定的位置,程序对内表行的寻址操作可通过关键字或索引进行。在对表

进行插入删除等操作时,各数据行在内存中的位置不变,系统仅重新排列各数据行的索引值。

   排序表也有逻辑索引,不同的是排序表总是按其表关键字升序排列后再进行存储,也就是在

内存中的位置发生改变。

   哈希表没有索引,只有关键字。

行访问方式

                    标准表                    排序表                 哈希表

索引访问             允许                       允许                 不允许

关键字访问           允许                       允许                  允许

相同值关键字行       可重复                   可重复或不可重复       不可重复 

推荐访问方式       主要通过索引               主要通过关键字        只能通过关键字  

 

具体到使用什么类型的内表     

    对于一个小于100行的内表,且很少使用关键字操作,则使用标准表没有效率问题;数据量

比较巨大,切不存在重复行,只需使用关键字访问的内表应定义为哈希表;排序表适用于运行

期内必须以某种排序形式出现的内表。

 

 

1.Standard Internal Tables: These tables have a linear index
and can be accessed using the index or the key. The response
time is in linear relationship with number of table entries.
These tables are useful when user wants to address
individual table entries using the index.
2.Sorted Internal Tables: These tables also have an index
and the key. But, the response time is in logarithmic
relationship with number of table entries, since it uses
binary search algorithm instead of linear search. These
tables are useful when user wants the table to be sorted
while additional entries have to be added.
3.Hashed Internal Tables: These tables have no index, but
have the key. The response time is constant irrespective of
number of table entries, since it uses a Hash algorithm.
These tables are useful when user wants to access the
entries with key only.
转自:
http://blog.sina.com.cn/s/blog_45afbbe50100ek5h.html

ABAP报表性能优化

原贴地址: 老宋的SAP博客

大部分ABAPer都是从SAP报表及打印开始学起的,大家也都认为写个SAP报表程序是最简单不过的事了。

但是实际情况真的如此吗?写报表时除了保证数据的准确性,您可曾考虑过报表的性能问题吗?

由于报表程序是被最多SAP用户所访问的,所以性能差的报表很可能会引来大量的抱怨和质疑,大大降低用户满意度。

最近做了较多性能优化方面的工作,颇有感触,在此进行归纳总结,希望对大家有所帮助,也欢迎大家讨论。

 

 

1,  关于表连接语句(INNER JOIN, LEFT JOIN...)

 

 写报表的时候,表与表之间的关联是不可避免的。通常而言,表连接语句要掌握的原则有:

 

(1) 将最有效的查询条件所对应的表放在第一位。换言之,让查询第一个表后所得到的结果集就尽可能小。

比如有一张报表叫做订单状态统计表,可能查完VBAK、VBAP后还查询LIPS、VTTP等,界面上的查询条件很多。不过据了解得知,该报表主要是查看昨天创建或前几天创建的订单。那么最有效的限制条件自然是订单创建日期,以及销售组织了,而表连接的主表宜选用VBAK。

 

(2) 确定了表连接的次序后,应考虑将查询条件尽量限制在靠前的表里。比如选择屏幕上有个物料号的查询条件,而我们知道订单VBAP和交货单LIPS均有物料号,那就应该视情况而定,如果表连接中VBAP更早出现,那么WHERE子句中就使用vbap~matnr IN s_matnr,反之就是lips~matnr IN s_matnr。

 

(3) 两个表之间进行连接的时候,应考虑关键字段或索引字段的作用。比如查询VTTP和LIPS时,关联关系是vttp~vbeln = lips~vbeln。那么vttp在前,lips在后,就会比较快,因为根据vttp的vbeln查询lips时,vbeln是lips的关键字段,速度较快。而反过来如果lips在前,那根据lips~vbeln查询vttp会慢一些,除非vbeln是vttp的索引字段。

 

 

2,  先构建RANGE再执行SQL语句

 

有时我们所能用的查询条件不是很理想,比如查询LIKP却必须用公司代码,而非销售组织。

此时普通做法是用LIKP与TVKO根据VKORG进行表联接,从而限制TVKO~BUKRS的值。

 

还有一种有效的办法是,通过TVKO查询到当期公司代码所对应的全部销售组织,从而组建一个RANGE出来,再根据此RANGE查询LIKP。当然要注意RANGE的行项目有上限的,在ECC6中大概2万行将导致ABAP DUMP。

提示:DATA r_vkorg TYPE RANGE OF likp-vkorg.

SIGN = ‘I’, OPTION = ‘EQ’, LOW = ‘XXXX’ 即可往r_vkorg中放入多个单值。

3,  For All Entries与Select Single的比较

就个人而言,笔者不是很喜欢For All Entries语句,因为它的缺点多于优点。很多人都会说,为什么呀,For All Entries不是比Select Single快么?事实到底怎样呢,让我们做个比较。

假设我们有个内表代表销售订单的行项目,该内表有10万行。此时我们要根据LIPS的VGBEL和VGPOS,查询这些订单行项目对应的交货单行项目。

 

如果用SELECT SINGLE的话写法很简单:

LOOP AT it_vbap INTO wa_vbap.

SELECT SINGLE vbeln posnr

FROM lips INTO (wa_vbap-vbeln_vl, wa_vbap-posnr_vl)

WHERE vgbel = wa_vbap-vbeln AND

vgpos = wa_vbap-posnr AND

vgtyp = ‘C’.

  MODIFY it_vbap FROM wa_vbap.

ENDLOOP.

 

如果用For All Entries则写法分2步:

SELECT vbeln posnr

FROM lips INTO TABLE it_lips

For All Entries IN it_vbap

WHERE vgbel = it_vbap-vbeln AND

vgpos = it_vbap-posnr AND

vgtyp = ‘C’. “此交货单是根据订单创建的

 

LOOP AT it_vbap INTO wa_vbap.

READ TABLE it_lips INTO wa_lips WITH KEY vgbel = wa_vbap-vbeln

vgpos = wa_vbap-vgpos.

IF sy-subrc = 0.

  wa_vbap-vbeln_vl = wa_lips-vbeln.

  wa_vbap-posnr_vl = wa_lips-posnr.

  MODIFY it_vbap FROM wa_vbap.

ENDIF.

ENDLOOP.

 

对于SELECT SINGLE而言,由于LIPS有个VGB的SAP自带索引,每次查询都挺快,即便循环10万次,速度虽然快不了但也没什么大的危害。

对于For All Entries的第一步,的确比SELECT SINGLE快些,本来10万次的SELECT SINGLE,变成了1万次的查询(如果BASIS设置了参数为10),每次查询10个订单行项目。但是第二步就很慢了, 暂估it_lips为8万行,则对于it_vbap的10万个行项目,有8万个行项目执行READ TABLE语句平均需要4万次才能搜索到it_lips的目标行,另有2万个行项目将读遍it_lips然后才发现没有对应的目标行。所以我们一共需要搜索48亿次,太慢了!

 

在此针对For All Entries的使用提出几点意见:

(1)如果是根据某数据量大的内表用For All Entries读取数据量小的配置表,比如TVAK/T006等,那不如把For All Entries直接去掉,把表里的几十条数据全部取出。

(2)使用For All Entries时,SELECT语句后面的字段必须包含所查表关键字段。比如上面的vbeln/posnr就是lips的关键字段。如果不含关键字段,比如SELECT lfimg FROM lips For All Entries ***,那么当LIPS中两个条目关键字段不同而lfimg相同时,会被SAP自动过滤掉一条。

(3)上面关于性能问题,应该利用BINARY SEARCH、SORTED TABLE或者HASHED TABLE来解决。详见下面第四节。

 

 

4,  关于BINARY SEARCH/SORTED TABLE/HASHED TABLE的使用

 

BINARY SEARCH即二分法查找,在保证内表按查询字段以升序排列的时候,可以采用二分法查找。二分法查找的速度很快,最大查询次数为log2n。以上面的例子来说,如果it_lips事先按vgbel和vgpos排好序,则每次查找最多不超过17次。则对于it_vbap的10万个行项目,仅100多万次就可以搞定了!

当使用READ TABLE语法时,如果查询字段跟SORTED TABLE的排序开始字段能匹配上,则SAP将自动采用二分法查找。比如it_lips是SORTED TABLE且以vgbel和vgpos排序,则当read table以vgbel进行查找时,系统会自动采用二分法。但如果read table以vgpos和其他字段进行查找,由于vgpos并非SORTED TABLE的第一排序字段,系统将采用直线查找,速度会慢很多。总之,SORTED TABLE的排序字段次序也很关键。

 

针对STANDARD TABLE排序后可以进行二分法查找,使用SORTED TABLE也可进行二分法查找,那么二者有什么区别呢?简单来说,由于SORTED TABLE自始至终都保持排序,如果需要对内部进行频繁的插入、删除操作,则不推荐使用SORTED TABLE,性能会很差。而另一方面,如果我们要用的是类似LOOP AT it_lips WHERE vgbel = ** 的语法(而非READ TABLE)时,对于STANDARD TABLE就无法采用二分法查找,或者说会很麻烦。而对于SORTED TABLE,系统会自动采用二分法优化查找过程。

 

至于HASHED TABLE,笔者用得也不太多。查看SAP的标准代码,貌似用得也没很多。理论上HASHED TABLE可以比SORTED TABLE更快些,但需要耗用更大的存储空间。当某程序采用了二分法查找之后,如果效果还不是很理想,建议可以用HASHED TABLE试试。

5,  将循环内的重复性工作进行缓冲

 

有时我们的内表数据量很大,但又不得不在每次循环的时候,都进行类似的一些操作,比如调用函数FI_PERIOD_DETERMINE获取某日期对应的会计年度和期间,调用函数MD_CONVERT_MATERIAL_UNIT进行单位转换,等等。每个函数的调用背后都要执行一系列的读表以及运算工作,程序的效率明显下降了。所以我们得想出有效的办法。

 

比如针对FI_PERIOD_DETERMINE的调用,可以改用循环前对函数G_PERIODS_OF_YEAR_GET的调用。根据公司代码BUKRS读取T001-PERIV,然后调用G_PERIODS_OF_YEAR_GET获取某会计年度每个会计期间对应的起始日期和结束日期。这样在循环内部,只要根据上面的结果即可算出某日期对应的会计年度和期间了。

 

又比如针对MD_CONVERT_MATERIAL_UNIT的调用。相信对于it_vbap的10万个行项目,物料号重复的有很多。所以可以先汇总物料号,然后一次性读取表MARM以存储换算关系。有了MARM的换算关系,循环中大量的单位换算就可以自己算了,如果无法换算的再考虑调用函数MD_CONVERT_MATERIAL_UNIT。(函数MD_CONVERT_MATERIAL_UNIT除了读取MARM的换算关系,还会考虑同一维度单位间的换算关系比如G和KG的关系,所以其功能更强大。)

 

 

6,  关于字段的增强以及TABLE INDEX的创建

 

这里提到字段的增强,主要是性能方面相关的。假设我们需要基于系统所有的billing document做个动作,比如将其导出到金税系统。至少有两种方案:第一是新建一个表,专门记录已经导出到金税的开票凭证;第二是在系统标准的开票凭证抬头表vbrk中新增一个字段,记录是否已导出到金税。

用户在处理业务的时候肯定会反复查询“未导出到金税”的所有开票凭证。那么第一种方案下,我们需要先查询VBRK表(比如得到1万条记录),然后针对自建表的记录(比如得到9800条记录)做个减法,最后得到200条记录的结果集。而第二种方案就快多了,查询VBRK的时候判断新字段=“未导出”即可。

随着业务的持续,VBRK表的条目将越来越多,而“未导出”的条目则会维持在一个较为平稳的数字上,为了有效区分历史数据和现用数据,可添加TABLE INDEX,提高报表的查询速度。很多SAP标准表都自带了一些索引,这些索引大都比较实用。

 

创建索引需要注意以下几点:

(1)索引会占用额外的数据库空间,还会降低插入/修改的速度(虽然可提高查询速度),所以需要考虑实用性,肯定不是越多越好。如果表中已有类似的索引,则不推荐新建。而对于容量大的、被多个程序访问的表加索引就更要谨慎了,比如VBFA、MSEG、FAGLFLEXA、LIPS、VBAP、EDIDC、STXH等等。

(2)创建索引时应注意字段的先后次序,MANDT是必须的而且都要放在第一位。字段的先后次序取决于实际业务需要。另外索引的字段不宜太多,字段越多占用的数据库空间就越多,对于插入/修改的影响也更大。

 

 

7,  选用一些替代表/替代字段(VBFA, SHP_IDX_)

曾做过一些类似于“未拣配交货单”、“未发货过账交货单”的报表,刚开始用的是LIKP、VBUK等表,速度并不理想。后来调试了标准程序VL06O,发现其用的表是SHP_IDX_PICK、SHP_IDX_GDSI等。原来系统在创建交货单的时候,也会更新这些临时表。当拣配完成,该条目就从SHP_IDX_PICK中删除。所以表SHP_IDX_PICK的条目数始终不多,查询速度很快。

同样的,当我们在多个表中进行查询时,可能不同的限制条件都能达到同样的结果集,但效率差异就很大,所以选用有效的字段非常关键。比如需要查询某销售组织某天已发货的销售订单,我们可以将VBAP与LIPS联查。此时查询条件VBAK-LIFSK=SPACE或VBAP-ABGRU=SPACE并不影响查询结果,但它们可以在第一时间就排除大量无关的订单,对于性能的提升帮助很大。

 

 

8,考虑企业的特点及数据量状况

 

做优化不是简单的技术活,既要考虑报表的实际需求,也要考虑企业的业务状况。比如采用零售模式的企业客户量很大(KNA1表条目多),批发模式的企业客户量较小;食品饮料行业的物料号一般不多,而机械行业的物料号则往往多而繁杂;零售业的订单量很大、时间性很强,所以最有效的查询条件往往就是组织编码+日期,部分行业则可能订单量小但价值高。只有充分考虑到企业的业务特点,才能更有效地提高报表性能。

动态取数据库表的方法

1.动态取数据库表展示ALV

REPORT ZBC_VARTAB0010.
*&---------------------------------------------------------------------*
*& Report  ZBC_VARTAB0010.
*&
*&---------------------------------------------------------------------*
*&
*&  ABAP 动态的实现任意表的ALV显示(学习动态构建表格和结构)
*&
*&---------------------------------------------------------------------*

type-pools:abap.
data lt_table type table of dfies.
data ls_table type dfies.

parameters p_name type objname default 'EKKO'.
parameters p_max  type i default 500.

initialization.

start-of-selection.

  call function 'DDIF_NAMETAB_GET'
  exporting
  tabname = p_name
  tables
* X031L_TAB =
  dfies_tab = lt_table
  exceptions
  not_found = 1
  others = 2.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
    with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  endif.

  data lr_struc type ref to cl_abap_structdescr.
  data lr_table type ref to cl_abap_tabledescr.
  data lr_type type ref to cl_abap_typedescr.
  data lr_data type ref to cl_abap_datadescr.
  data l_string type string.
  data lt_comp type abap_component_tab.
  data ls_comp like line of lt_comp.
  data e_wa type ref to data.
  data e_table type ref to data.


  field-symbols <fs_table> type standard table.
  field-symbols <fs_struc> type any.

  loop at lt_table into ls_table.
    concatenate ls_table-tabname '-' ls_table-fieldname into l_string.
* L_STRING = LS_COMP-NAME.
    ls_comp-name = ls_table-fieldname.
    call method cl_abap_datadescr=>describe_by_name
      exporting
        p_name         = l_string
      receiving
        p_descr_ref    = lr_type
      exceptions
        type_not_found = 1
        others         = 2.
    if sy-subrc <> 0.
      message id sy-msgid type sy-msgty number sy-msgno
      with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    endif.


    ls_comp-type ?= lr_type.
    append ls_comp to lt_comp.
    clear ls_comp.
  endloop.

  call method cl_abap_structdescr=>create
    exporting
      p_components = lt_comp
    receiving
      p_result     = lr_struc.

  call method cl_abap_tabledescr=>create
    exporting
      p_line_type = lr_struc
    receiving
      p_result    = lr_table.

  create data e_wa type handle lr_struc.
  create data e_table type handle lr_table.


  assign e_wa->* to <fs_struc>.
  assign e_table->* to <fs_table>.



  select *
    up to p_max rows
    into corresponding fields of table <fs_table>
    from (p_name).

  call function 'REUSE_ALV_GRID_DISPLAY'
    exporting
      i_structure_name = p_name
    tables
      t_outtab         = <fs_table>
    exceptions
      program_error    = 1
      others           = 2.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
    with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  endif.

2.有个FUNCTION 可以CALL的



REPORT ZBC_VARTAB0020.
type-pools:abap.
data lt_table type table of dfies.
data ls_table type dfies.
DATA SELTAB LIKE RSPARAMS.
parameters p_name type objname default 'MAKT'.
INITIALIZATION.
START-OF-SELECTION.
CALL FUNCTION 'RS_TABLE_LIST_CREATE'
  EXPORTING
    TABLE_NAME               = p_name
*   ACTION                   = 'ANZE'
*   WITHOUT_SUBMIT           = ' '
*   GENERATION_FORCED        =
*   NEW_SEL                  =
*   NO_STRUCTURE_CHECK       = ' '
*   DATA_EXIT                = 'X'
* IMPORTING
*   PROGNAME                 =
* TABLES
*   SELTAB                   =
* EXCEPTIONS
*   TABLE_IS_STRUCTURE       = 1
*   TABLE_NOT_EXISTS         = 2
*   DB_NOT_EXISTS            = 3
*   NO_PERMISSION            = 4
*   NO_CHANGE_ALLOWED        = 5
*   OTHERS                   = 6
          .
IF SY-SUBRC <> 0.
* Implement suitable error handling here
ENDIF.


The demo example of variable table

---------------use se38 to create the program-----------

PARAMETERS:P_NAME TYPE TABNAME.
DATA: DYN_TABLE TYPE REF TO DATA.
DATA: DYN_WA TYPE REF TO DATA.
FIELD-SYMBOLS: <DYN_TABLE> TYPE TABLE, "内表指针
               <DYN_WA>    TYPE ANY.    "工作区指针
*创建动态表结构
CREATE DATA DYN_TABLE TYPE TABLE OF (P_NAME).
*创建动态内表
ASSIGN DYN_TABLE->* TO <DYN_TABLE>.
*创建动态工作区结构
CREATE DATA DYN_WA LIKE LINE OF <DYN_TABLE>.
*创建动态工作区
ASSIGN DYN_WA->* TO <DYN_WA>.
*从动态表中取数到动态内表中
 SELECT *
  INTO CORRESPONDING FIELDS OF TABLE <DYN_TABLE> UP TO 100 ROWS
  FROM (P_NAME).
*对取出数据进行处理
LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
  "内表数据处理
ENDLOOP.
*显示内表中的数据
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
  EXPORTING
    I_STRUCTURE_NAME = P_NAME
  TABLES
    T_OUTTAB         = <DYN_TABLE>
  EXCEPTIONS
    PROGRAM_ERROR    = 1
    OTHERS           = 2.
IF SY-SUBRC <> 0.
  MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
          WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.



The Header File of C++

1.Definition of a class

- in c++ , separated .h and .cpp files are used to define one class.

- Class declaration and prototypes in that class are in the header file(.h).

- All the bodies of these functions are in the source file(.cpp)

2.The header files 

- if a function is declared in a header file , you must include the header file everywhere the function is used and where the function is defined.

- if a class is declared in a header file , you must include the header file everywhere the class is used and where class member functions are defined.

3.Header = interface 

- The header is a contract between you and the user of your code.

- The compile enforces the contract by requiring you to declare all structures and functions before they are used.

4.Declarations vs definitions

- A .cpp file is a compile unit 

- only declarations are allowed to be in .h

- extern variables 

- function prototypes

- class/struct declaration

5.#include 

- #include is to insert the included file into the .cpp file at where the #include statement is .

- #include "xx.h" : first search in the current directory , then directories declared somewhere

- #include <xx.h> :search in the specified directories 

- #include <xx>:same as #include <xx.h>

The Basic Principle of OOP OF C++

1.Object send and receive messages(objects do things)

the messages are : 

- composed by the sender 

- interpreted by the receiver

- implemented by methods

the messages 

- may cause receiver to change state

- may return results

2.Object vs Class

object (cat)

- represent things , event , or concept

- respond to message at run-time

classes (cat class)

- define properties of instances

- act like types in c++

3.OOP CHARACTERISTICS

- Everything is an object

- A program is a bunch of object telling each other what to do by sending messages.

- Each object has its own memory made up of  other objects.

- Every object has a type.

- All objects of a particular type can receive the same messages.

4.An object has an interface 

- The interface is the way it receives messages.

- It is  defined in the class the object belong to.  

5.Functions of the interface ( coupling )

- Communication 

- Protection

6.The Hidden Implementation

- Inner part of an object , data members to present its state , and the actions it takes when messages is received is hidden.

- Class creators vs Client programmers

- Keep client progrmmers' hands off portions they should not touch.

- Allow the class creators to change the internal working of the class without worrying about how it will affect the client programmers.

7.Encapsulation

- bundle data and methods dealing with these data together in an object .

- hide the details of the data and the action .

- restrict only access to the publicized methods.