分类目录归档:未分类

java基础类型知识

Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。
原始类型封装类
boolean –>Boolean
char —>Character
byte –>Byte
short –>Short
int –>Integer
long –>Long
float –>Float
double –>Double
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的 数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。同时为了面向对象操作的一致性,这些基本类型都有相应的封装类型:Integer、Short、 Long、Byte、Float、Double、Character等。      
因为封装类型是对象,所以可以进行相应的很多对象能力函数操作,这样就可以提供很多基本类型难以完成的工作的完成和实现。   
你可以通过以下方式来声明该类型。

int a,a为int类型的变量
char a,a为char类型的

String对象

1. 首先String不属于8种基本数据类型,String是一个对象。

  因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

  2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

  3. String str=”punkll”;

   String str=new String (“punkll”);的区别:

  在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

  常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

  看例1:

  String s0=”punkll”;

  String s1=”punkll”;

  String s2=”punk” + “ll”;

  System.out.println( s0==s1 );

  System.out.println( s0==s2 );

  结果为:

  true

  true

  首先,我们要知结果为道Java会确保一个字符串常量只有一个拷贝。

  因为例子中的s0和s1中的”punkll”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”punk”和”ll” 也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是 常量池中”punkll”的一个引用。

  所以我们得出s0==s1==s2;

  用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

  看例2:

  String s0=”punkll”;

  String s1=new String(”punkll”);

  String s2=”punk” + new String(“ll”);

  System.out.println( s0==s1 );

  System.out.println( s0==s2 );

  System.out.println( s1==s2 );

  结果为:

  false

  false

  false

  例2中s0还是常量池中”punkll”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”punkll”的引用,s2因为有后半 部分new String(“ll”)所以也无法在编译期确定,所以也是一个新创建对象”punkll”的应用;明白了这些也就知道为何得出此结果了。

面向对象的三个基本特征


面向对象的三个基本特征是:封装、继承、多态。

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承

面向对象编程 (OOP) 语言的一个主要功能就是继承。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为基类父类超类

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过继承Inheritance)和组合Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

 

继承概念的实现方式有三类:实现继承、接口继承和可视继承。

Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;

Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

Ø         可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是属于关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class

OO开发范式大致为:划分对象抽象类将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

 

多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

实现多态,有二种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

其实,重载的概念并不属于面向对象编程,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_funcstr_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是覆盖。 当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法 确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对 象也无关!引用一句Bruce Eckel的话:不要犯傻,如果它不是晚邦定,它就不是多态。

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了――代码重用。而多态则是为了实现另一个目的――接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用家谱中任一类的实例的某一属性时的正确调用。

柏林墙的逃亡(摘自百度百科)

1961年8 月,一个沉闷的夏天。对于大量东德人经柏林逃往西方已经忍无可忍的东德人和苏联人搞了一个漂亮的偷袭。8 月12日凌晨1 点,2 万多军队突然开到东西柏林边境,立刻开始了修筑柏林墙的工程。应该说,这个以我国长城命名的工程,准备还是很充分的,绝对不是豆腐渣,仅仅到13日凌晨, 第一期工程全部完工,整个东西柏林被铁丝网全部分割,再加路障。柏林墙正式树立了起来。
然而上帝实在会开玩笑,就在柏林墙的修筑过程中,东德人就开始了翻越柏林墙,逃亡西德的"柏林 墙传说"。东德人的争分夺秒,只争朝夕的精神,给柏林墙的历史研究留下了千古之迷,到底是先有柏林墙,再有翻越行动,还是未等墙树起来,就已经开始了翻 越,竟然永远无法得到一个答案了。
历史记载,柏林墙初步完成,即东西柏林正式分割,在13日中午12点37分,最后一个路口宣布 封锁为标志。但就在13日,最早明白过来的东德人已经开始用生命搏击柏林墙,当天,一位技工跨过正在树立的铁丝网跳进了西柏林,有人跳进运河游到了西柏 林。然而,天意弄人,谁也没想到记录他们踏上西德领土的时间。13日上午,西德人涌向柏林墙,向墙那边的同胞投掷自己的通行证,身份证件。到苏联军队能够 阻止这一举动前,数以千计的证件已经被扔到了东德同胞的手里。大批东德人借机混在返回西柏林的西德人中间偷渡逾越了柏林墙。
下面就介绍几个逃过柏林墙,争取自由的人!

天意弄人

13日下午,柏林墙树立以后,第一个逾越柏林墙的人出现了。一个青年在光天化日之下,用百米冲 刺的速度飞奔向铁丝网。但是,三名警察追上了他,将他打倒在地,谁也没有想到,被打倒的他竟奇迹般又站了起来,夺过警察的枪,一边与警察对峙一边继续向西 柏林飞奔。警察是尽职的,他们不顾这个年轻人的枪,冲上去和他又一次扭打成一团,并且一刀刺进青年人的膝盖。这次这个年轻人失去了奔跑的能力,面对三个警 察,结局已经注定。然而,上天决心要给大家看一幕喜剧而不是悲剧。就在此刻,西柏林群众雷鸣般的怒吼惊醒了三名警察,他们已经越过了柏林墙,现在是在西德 的土地上,他们不再是警察,而成了违法者。他们扔下青年跑回柏林墙的另一侧。这个青年拖著残废的腿,一边拼命呼救一边爬到了西柏林。
事后证明,这是一个大大的误会。事实上柏林墙并不是沿东德西德的边境修筑的,而是偏东德一侧, 这是为了保证,即使你越过了柏林墙,你仍然在东德土地上,警察和军队仍然有权力和能力开枪将你击毙。当时那三位警察并没有越界,他们大可以合法将那个青年 绑回东德。然而,面对这柏林墙上的第一次交锋,他们误会了,害怕了,那个青年简直是奇迹般的竟然这样逃脱了已经笼罩住了自己的厄运。

幽默的逃亡

要说最可爱的逃亡者,颇有几个竞争者,首先是两位大情圣,一个是阿根廷人,一个是澳大利亚人。大家看看他们逃亡的手段就可以知道,也就是他们能做出来,死脑筋的德国人就是再有几百万人逃亡,也做不出这么幽默的计划来。
柏林墙边的死窗户。街道在西方, 楼房属于东方。楼房上的窗口就是著名的”死窗户",被砌死以阻止人民逃跑到西柏林。 柏林墙并不是铁板一块,总有那么几个门,几个交通站。于是情人被困在东柏林的两位就打起了交通站的主意。经调查研究,交通站是靠栏杆来封锁交通的,虽然栏 杆结实,撞不断,但是栏杆比较高,如果汽车足够矮,可以从栏杆底下直接钻过去。于是计划诞生了,把自己的亲爱的放在行李箱里,趁警察不注意,开足马力,一 下从栏杆下面钻到西柏林就行了。说干就干,澳大利亚人就这么把自己的新娘子接到了西柏林。如果故事到此为止,那就不存在什么幽默了。但是这时候,阿根廷人 出场了,他充分表现了南美人民的热血沸腾,但不爱动脑子的特点,他认为这个计划不错,决定自己也照办煮碗。所谓照办,真的是照办,他居然连车子都是直接找 澳大利亚人借的同一辆车!说起来也是,这么矮的车本来就不好找。
问题是,他一点伪装都没有做,连车牌都不换,就这么开了去。阿根廷人开著这辆已经被报纸报道得 详细得不能再详细的车,大摇大摆开进东柏林。东德警察一看,这车怎么这么眼熟,但是谁也猜不到天下还真有这么大胆的人。警察问"这车,以前是不是来过东 德?"阿根廷人脸不红心不跳的回答,"当然没有啦"。警察自己也糊涂了,大手一挥,放行了!结果是,在一个星期以后,同一辆车,把另一对情侣,用同样的方 式带到了西柏林。在他们举行婚礼之际,悲愤的东德警察把栏杆下面装了无数垂直的铁条,别说是车,就是条蛇也休想从栏杆下面再钻出去!

地道冒险

五岁的小男孩。他家经过地道从柏林墙的下面钻到了西柏林。这个地道挖了整整6 个月。而且因为东柏林警察便衣密布,地道不得不从西柏林挖掘。要求是绝对不许做地面测量,还必须正好挖到被接应者的厕所里。为了不被地面人员发现,地道深入地下12米!
这样庞大的工程,这样长的时间,真不知道逃亡者是如何承受这样的心理压力如此之久的。但这个孩子什么也不知道。当他从地道口出现在西柏林的时候,面对记者和救援者人群发表感想如下:"这个大洞洞怪吓人的,不过没有野兽"

功败垂成

1961年,18岁的彼得。菲西特就是这么一个人。他已经爬到了柏林墙的顶部,只需要再加最后一把劲,就可以达成目标,就在这个时候,枪声响了……
彼得滑落回柏林墙东侧。悲剧还没有完,身中数弹的彼得倒在柏林墙下,血流如注,我不知道东德的 警察是一时不敢承担责任,跑去请示上级,还是真的就已经下了杀心。彼得就这样在墙下躺了50分钟,没有一个东德警察前来管他。彼得的呼喊声一点一点的低下 去了,低下去了。西柏林的人群爆发出愤怒的抗议声:“你们是杀人犯”“你们是法西斯!”上千群众怒吼著。西德的警察冒险跑到柏林墙边(前面已经说过,这是 极其危险的,柏林墙西侧依然是东德的土地,警察已经"越界",完全可能被枪击)把急救包扔向彼得。但是太晚了,彼得已经失去了自救的能力。彼得终于停止了 呼吸。他的血已经流尽了,在他蓝眼睛里最后映出的,依然是东柏林。50分钟以后,东德警察抬走了他的尸体。

梦想的力量

如果说彼得最大的不幸在于他最终没有成功,我不知道下面这个最后"成功" 的例子,是不是算幸运。在柏林墙刚完成的那一年,由于墙还不是很坚固,有人就想出了办法,开重型车辆直接撞墙!直接冲开柏林墙进入西德。1961年,这类事件多达14起。
逃亡者要面对的绝不仅仅是坚固的高墙,还有来自军队和警察的密集射击。有军事常识的朋友都知 道,对于穿透力极强的子弹,民用的车壁,车门根本就是nothing,香港电影里躲到小轿车后面就可以逃开对方射击的镜头完全是搞笑。所以,用这个办法冲 击柏林墙的人,实际上等于完全不设防的穿行在枪林弹雨中,去争取一次严重交通事故的机会!
布鲁希克和他的同伙同样是利用大客车冲击柏林墙,但是他们的行动从一开始就被发现了。军队和警 察从多个方向向客车密集射击,客车起火燃烧,弹痕累累!还好,客车质量过硬,不但没有熄火,还在布鲁希克良好的驾驶下奋勇加速,一声巨响,柏林墙被撞开了 一个大缺口,整个客车冲进了西柏林!欢呼的人群拥上来迎接,却被眼前的景象震惊了,驾驶座上的布鲁希克身中19 弹,他是用生命的最后意志坚持加速,冲向柏林墙的。当客车冲进西柏林的那一刻,布鲁希克停止了呼吸。柏林人展开了一场争论,布鲁希克究竟有没有看到他梦想 看到的西柏林?最后是一个现场镜头宽慰了大家,从镜头上看,客车驾驶座位于西柏林之后,布鲁希克还有一个抬头的动作。是的,那时候他还活著!他的眼睛最后 映出的,是他梦想中的迦南西柏林!他是一个成功者。

“潜水艇”逃亡

1968 年,一位东德青年利用河流潜水到达西德。大家心目中的潜水是什么样的?潜水服?潜水镜?总之他一个人能有多大本事,还一切都必须自己造,最多是一点粗糙的 个人潜水工具罢?这位青年自己造的是潜艇!他用的是摩托车马达,配上自己组装的钢板,还有导航,压缩气体等系统。硬是在家造出了一个个人用的小潜水艇。质 量如何?我看可以通过ISO9002 国际认证。这潜水艇在水下航行了超过5 个小时,才从西德那边冒出来,其中没有发生任何事故。有同学说了,5 个小时是不是太长了一点,那是没办法的事情,你试试拿个小摩托的马达去潜水看。这小潜水艇当然是一个奇迹,该青年的逃亡过程使他立刻在西德找到了工作,各 大机械公司竞相聘用该青年为设计师。听说后来他还真在机械设计上大有成就。

象征自由的热气球

1979年某夜晚,从东德一个家庭的后院升起了一个巨大的热气球。气球下面的吊篮里装著两个家庭–两对夫妇和他们的四个孩子。这个气球完全由这两个家庭 手工制成,花了数年的时间。在此期间,两个家庭自学成才,从材料学,工程学,气体动力学,气象学……一直到建立家庭实验室,最后成功的在家庭的后院里制作 完成了这个高达28米的热气球!经调查,此热气球是欧洲历史上最大的热气球,被记入吉尼斯世界记录!这个热气球在通过柏林墙的时候,被警察发现了。警察目 瞪口呆之余,还算记得开枪射击。这一射击,该气球良好的工艺水准就发挥了出来。逃亡者操纵热气球一下升高到了2800米以上的高空,不但枪打不到,连探照 灯都照不到!警察只好紧急呼叫空军支援,寻找一个热气球,把它打下来。苏联空军"苏","米"战机立刻出动,但是热气球在28分钟的飞行以后,已经完成了 使命,安全落地。问题是,当气球被发现以后,两家人决定立刻降落,以避免被战机击落。这一 "紧急降落",就谁也摸不准方向了,降落的地点无法确定。到底是已经到了西德,还是被迫降在东德,谁也不知道。面对未知的前景,8 个人都失去了验证的勇气。他们根本不敢走出这个气球,就这样躲在吊篮里长达24小时之久。他们已经没有勇气亲自揭晓自己的命运了。他们唯一能作的,就是祈 祷。降落整整24小时以后,军人来了,揭开了气球。他们对这8 个逃亡者说出了他们盼望了多少年的话。"你们自由了,这里是西德领土。"

女人的爱情与修养有关

一朋友说:“女人有四种境界:浅而清澈型;浅 而混浊型;深而混浊型;深而清澈型”,其中属第四种境界最高,不禁觉得精辟,索性拿来一谈,其实爱情与品德有关。


浅而清澈型的女人比较可爱,简单且又真 诚,纯粹且又单纯,她们没有太多的欲望,没有太多的奢求,只有一颗面对生活与爱情的真诚的心。既没有太多的城府,也没有太多的计较,虽然没有知性女人的聪 慧,却与其相处犹如童年的梦幻,因为简单,所以快乐。若能遇上这等女人,那便会有一个简单且活泼的生活。


浅而混浊型的女人在这个物欲横流的社会比较常见, 浅是说头脑简单,阅历稀少,浑浊是说欲望颇多,奢望强烈,自己都搞不清楚自己需要什么。这类女人一经接触便很容易了解,由于比较粗浅,言语内外,动静之 间,便把那份浑浊暴露的体无完肤,可悲的是这类女人却还比较自爱,常常把自己的打扮得简单而看起来单纯,且故作纯粹,只是举止之间,总是摆脱不了那份复杂 混浊矛盾的内心,给人不舒服的感觉。若是遇上这等女人,那便会有一个劳碌奔波的生活。


深而混浊型的女人颇为矛盾,丰富的阅历与经历残酷的现实早已经麻木了 那份曾经纯粹的心,一方面渴望真诚且又单纯简单的生活与感情,一方面又不敢面对残酷与现实的生活,终日忐忑与现实与梦幻之间,忽而相信感情,追求生活,忽 而沉醉现实,自甘堕落。说其简单,却不简单,说其成熟,却不成熟。只能称之为矛盾且无奈。这类女人其实需要一份或者一片希望来走出自己的内心的阴暗,只是 繁华的都市阑珊的星光往往让人看不到希望的灯火。


深而清澈型的女人算得上女人中的极品,经历俗事的风雨与坎坷,经历感情的磨砺与奔波,还能保持一份纯粹的 心灵与灵魂,已经不能用任何语言去表达这类女人的美丽与唯美。其实爱情与修养有关,就像于丹讲论语一般,虽然不太赞成她的某些观点,但是总得思路还是对 的,每个人的生活品质,感情追求,其实其直接决定的原因是每个人的个人品味与修养。这个修养,包含太多,甚至看似不相关的素质都是包含其中,以前一直在谈 论修身养性的问题,现在看来是对的,人生就像一门经营哲学,感情,生活,事业都需要用自身的素质修养去驾驭的,每个人的生活的品质层次直接来源于他的个人 修养,没有抱怨,没有不公,那便是生活。你对爱情生活的认知程度,对责任义务的把握程序直接决定了你可以遇到一个什么样的人,不要去抱怨对方的问题,其实 那便是你自己的选择。中国有一句话:”物以类聚,人以群分”,还是真的有道理的。就像老百姓常说的,看看一个人的老公,或者老婆,便知道对方是什么人了

十进制转二进制的算法

方法一:

int main()
{
  int  ival, n = 0;
  char bin[32];
  scanf("%d", &ival);
  while(ival > 0) {
    bin[n++] = ival % 2;
    ival /= 2;
  }
  for(n–; n >= 0; n–)
    printf("%d", bin[n]);
  printf("n");
  getch();
}

方法二:

int main()
{
  int  ival, n = 0;
  char bin[32];
  scanf("%d", &ival);
  while(ival > 0) {
    bin[n++] = ival & 0x01;
    ival >>= 1;
  }
  for(n–; n >= 0; n–)
    printf("%d", bin[n]);
  printf("n");
  getch();
}

C++的4种类型转换

一、C 风格(C-style)强制转型如下:

    (T) expression // cast expression to be of type T
    函数风格(Function-style)强制转型使用这样的语法:
    T(expression) // cast expression to be of type T
    这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。我把这两种形式称为旧风格(old-style)的强制转型。

   二、 C++的四种强制转型形式:

  C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):
const_cast(expression)
dynamic_cast(expression)
reinterpret_cast(expression)
static_cast(expression)

  每一种适用于特定的目的:

  ·dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
   
    ·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
   
·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。

  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。

旧风格的强制转型依然合法,但是新的形式更可取。首先,在代码中它们更容易识别(无论是人还是像 grep 这样的工具都是如此),这样就简化了在代码中寻找类型系统被破坏的地方的过程。第二,更精确地指定每一个强制转型的目的,使得编译器诊断使用错误成为可 能。例如,如果你试图使用一个 const_cast 以外的新风格强制转型来消除常量性,你的代码将无法编译。

== 
==  dynamic_cast .vs. static_cast
==

class B { … };
class D : public B { … };

void f(B* pb)
{
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}

If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0.

If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

    即dynamic_cast可用于继承体系中的向下转型,即将基类指针转换为派生类指针,比static_cast更严格更安全。 dynamic_cast在执行效率上比static_cast要差一些,但static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随 着不安全性.static_cast覆盖的变换类型除类层次的静态导航以外,还包括无映射变换,窄化变换(这种变换会导致对象切片,丢失信息),用 VOID*的强制变换,隐式类型变换等…

==
==  static_cast .vs. reinterpret_cast
==

    reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它.我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的.(这句话是C++编程思想中的原话)

    static_cast 和 reinterpret_cast 操作符修改了操作数类型. 它们不是互逆的; static_cast 在编译时使用类型信息执行转换, 在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作数相对是安全的. 另一方面, reinterpret_cast 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换, 例子如下:

   int n=9; double d=static_cast < double > (n);

    上面的例子中, 我们将一个变量从 int 转换到 double. 这些类型的二进制表达式是不同的. 要将整数 9 转换到 双精度整数 9, static_cast 需要正确地为双精度整数 d 补足比特位. 其结果为 9.0. 而reinterpret_cast 的行为却不同:

    int n=9;
    double d=reinterpret_cast<double & > (n);

FALSE/TRUE与false/true的区别

1.FALSE/TRUE与false/true的区别:
false/true是标准C++语言里新增的关键字,而FALSE/TRUE是通过#define,这要用途
是解决程序在C与C++中环境的差异,以下是FALSE/TRUE在windef.h的定义:
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
也就是说FALSE/TRUE是int类型,而false/true是bool类型;所以两者不一样的,只不过
我们在使用中没有这种感觉,因为C++会帮你做隐式转换。
2.bool的大小与BOOL的区别:
bool在C++里是占用1字节,而BOOL是int类型,int类型的大小是视具体环境而定的;所以
来说:false/true只占用1个字节,而TRUE/FALSE视具体环境而言,以下是BOOL在windef
.h中的定义:typedef int BOOL;
3.NULL与0的区别:
还是让我们看一下windef.h中NULL的定义:
#ifndef NULL
#ifdef __cplusplus//这个是指示是用C++来编译程序
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
所以说:它们没有区别,只不过在C里面会做一个强制类型转换。

sscanf 特别用法(转)

获取/和@之间的字符串怎么做
C程序里面有什么函数吗?
 
#include <stdio.h>
int main()
{
    const char* s = "iios/12DDWDFF@122";
    char buf[20];
    sscanf( s, "%*[^/]/%[^@]", buf );
    printf( "%sn", buf );
    return 0;
}
结果为:12DDWDFF
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
函数原型:
int scanf( const char *format [,argument]… );
其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type  |  ‘ ‘ |  ‘t’ | ‘n’ | 非%符号},
注:{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
 
 width:宽度,一般可以忽略,用法如:
const  char sourceStr[] = "hello, world";
char buf[10] = {0};
sscanf(sourceStr, "%5s", buf);   //%5s,只取5个字符
cout << buf<< endl;
结果为:hello
 {h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
type :这就很多了,就是%s,%d之类。
 
特别的:
%*[width] [{h | l | I64 | L}]type  表示满足该条件的被过滤掉,不会向目标参数中写入值。如:
const  char sourceStr[] = "hello, world";
char buf[10] = {0};
sscanf(sourceStr, "%*s%s", buf);   //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
cout << buf<< endl;
结果为:world
支持集合操作:
         %[a-z]  表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
         %[aB’]  匹配a、B、’中一员,贪婪性
         %[^a]    匹配非a的任意字符,贪婪性
         是不是感觉眼熟了啊,不错,这和正则表达式很相似,而且仍然支持过滤,即可以有%*[a-z].如:
 
    const char* s = "iios/12DDWDFF@122";
    char buf[20];
    sscanf( s, "%*[^/]/%[^@]", buf );
    printf( "%sn", buf );
先将 "iios/"过滤掉,再将非‘@’的一串内容送到buf中,cool.得到结果。

简单常识――关于stream

从文件中读入一行

简单,这样就行了:

ifstream ifs("input.txt");
char buf[1000];

ifs.getline(buf, sizeof buf);

string input(buf);

当然,这样没有错,但是包含不必要的繁琐和拷贝,况且,如果一行超过1000个字符,就必须用一个循环和更麻烦的缓冲管理。下面这样岂不是更简单?

string input;
input.reserve(1000);
ifstream ifs("input.txt");
getline(ifs, input);

不仅简单,而且安全,因为全局函数 getline 会帮你处理缓冲区用完之类的麻烦,如果你不希望空间分配发生的太频繁,只需要多 reserve 一点空间。

这就是“简单常识”的含义,很多东西已经在那里,只是我一直没去用。

—————————————————————————

一次把整个文件读入一个 string

我希望你的答案不要是这样:

string input;
while( !ifs.eof() )
{
    string line;
    getline(ifs, line);
    input.append(line).append(1, ‘n’);
}

当然了,没有错,它能工作,但是下面的办法是不是更加符合 C++ 的精神呢?

string input(
    istreambuf_iterator<char>(instream.rdbuf()),
    istreambuf_iterator<char>()
);

同样,事先分配空间对于性能可能有潜在的好处:

string input;
input.reserve(10000);
input.assign(
    istreambuf_iterator<char>(ifs.rdbuf()),
    istreambuf_iterator<char>()
);

很简单,不是么?但是这些却是我们经常忽略的事实。
补充一下,这样干是有问题的:

    string input;

    input.assign(

        istream_iterator<char>(ifs),

        istream_iterator<char>()

    );

因为它会忽略所有的分隔符,你会得到一个纯“字符”的字符串。最后,如果你只是想把一个文件的内容读到另一个流,那没有比这更快的了:

    fstream fs("temp.txt");

    cout << fs.rdbuf();

因此,如果你要手工 copy 文件,这是最好的(如果不用操作系统的 API):

   ifstream ifs("in.txt");

   ofstream ofs("out.txt");

   ofs << in.rdbuf();

————————————————————————-

open 一个文件的那些选项

ios::in     Open file for reading
ios::out    Open file for writing
ios::ate    Initial position: end of file
ios::app    Every output is appended at the end of file
ios::trunc  If the file already existed it is erased
ios::binary Binary mode

————————————————————————-

还有 ios 的那些 flag

flag effect if set
ios_base::boolalpha input/output bool objects as alphabetic names (true, false).
ios_base::dec input/output integer in decimal base format.
ios_base::fixed output floating point values in fixed-point notation.
ios_base::hex input/output integer in hexadecimal base format.
ios_base::internal the output is filled at an internal point enlarging the output up to the field width.
ios_base::left the output is filled at the end enlarging the output up to the field width.
ios_base::oct input/output integer in octal base format.
ios_base::right the output is filled at the beginning enlarging the output up to the field width.
ios_base::scientific output floating-point values in scientific notation.
ios_base::showbase output integer values preceded by the numeric base.
ios_base::showpoint output floating-point values including always the decimal point.
ios_base::showpos output non-negative numeric preceded by a plus sign (+).
ios_base::skipws skip leading whitespaces on certain input operations.
ios_base::unitbuf flush output after each inserting operation.
ios_base::uppercase output uppercase letters replacing certain lowercase letters.

There are also defined three other constants that can be used as masks:

constant value
ios_base::adjustfield left | right | internal
ios_base::basefield dec | oct | hex
ios_base::floatfield scientific | fixed

————————————————————————–

用我想要的分隔符来解析一个字符串,以及从流中读取数据

这曾经是一个需要不少麻烦的话题,由于其常用而显得尤其麻烦,但是其实 getline 可以做得不错:

    getline(cin, s, ‘;’);   

    while ( s != "quit" )

    {

        cout << s << endl;

        getline(cin, s, ‘;’);

    }

简单吧?不过注意,由于这个时候 getline 只把 ; 作为分隔符,所以你需要用 ;quit; 来结束输入,否则 getline 会把前后的空格和回车都读入 s ,当然,这个问题可以在代码里面解决。

同样,对于简单的字符串解析,我们是不大需要动用什么 Tokenizer 之类的东西了:

#include <iostream>

#include <sstream>

#include <string>



using namespace std;



int main()

{

    string s("hello,world, this is a sentence; and a word, end.");

    stringstream ss(s);

   

    for ( ; ; )

    {

        string token;

        getline(ss, token, ‘,’);

        if ( ss.fail() ) break;

       

        cout << token << endl;

    }

}

输出:

hello

world

 this is a sentence; and a word

 end.

很漂亮不是么?不过这么干的缺陷在于,只有一个字符可以作为分隔符。

————————————————————————–

把原本输出到屏幕的东西输出到文件,不用到处去把 cout 改成 fs

#include <iostream>
#include <fstream>
using namespace std;
int main()
{    
    ofstream outf("out.txt"); 
    streambuf *strm_buf=cout.rdbuf();    
    cout.rdbuf(outf.rdbuf()); 
    cout<<"write something to file"<<endl; 
    cout.rdbuf(strm_buf);   //recover 
    cout<<"display something on screen"<<endl;
    system("PAUSE");
    return 0;
}
 

输出到屏幕的是:

display something on screen

输出到文件的是:

write something to file

也就是说,只要改变 ostream 的 rdbuf ,就可以重定向了,但是这招对 fstream 和 stringstream 都没用。

————————————————————————–

关于 istream_iterator 和 ostream_iterator

经典的 ostream_iterator 例子,就是用 copy 来输出:

#include <iostream>

#include <fstream>

#include <sstream>

#include <algorithm>

#include <vector>

#include <iterator>



using namespace std;



int main()

{  

    vector<int> vect;

    for ( int i = 1; i <= 9; ++i )

        vect.push_back(i);

       

    copy(vect.begin(), vect.end(),

        ostream_iterator<int>(cout, " ")

    );

    cout << endl;

   

    ostream_iterator<double> os_iter(cout, " ~ ");

    *os_iter = 1.0;

    os_iter++;

    *os_iter = 2.0;

    *os_iter = 3.0;

}

输出:

1 2 3 4 5 6 7 8 9

1 ~ 2 ~ 3 ~

很明显,ostream_iterator 的作用就是允许对 stream 做 iterator 的操作,从而让算法可以施加于 stream 之上,这也是 STL 的精华。与前面的“读取文件”相结合,我们得到了显示一个文件最方便的办法:

    copy(istreambuf_iterator<char>(ifs.rdbuf()),

         istreambuf_iterator<char>(),

         ostreambuf_iterator<char>(cout)

    );

同样,如果你用下面的语句,得到的会是没有分隔符的输出:

    copy(istream_iterator<char>(ifs),

         istream_iterator<char>(),

         ostream_iterator<char>(cout)

    );

那多半不是你要的结果。如果你硬是想用 istream_iterator 而不是 istreambuf_iterator 呢?还是有办法:

    copy(istream_iterator<char>(ifs >> noskipws),

         istream_iterator<char>(),

         ostream_iterator<char>(cout)

    );

但是这样不是推荐方法,它的效率比第一种低不少。
如果一个文件 temp.txt 的内容是下面这样,那么我的这个从文件中把数据读入 vector 的方法应该会让你印象深刻。

12345 234 567
89    10

程序:

#include <iostream>

#include <fstream>

#include <algorithm>

#include <vector>

#include <iterator>



using namespace std;



int main()

{  

    ifstream ifs("temp.txt");

   

    vector<int> vect;

    vect.assign(istream_iterator<int>(ifs),
        istream_iterator<int>()
    );




    copy(vect.begin(), vect.end(), ostream_iterator<int>(cout, " "));

}

输出:

12345 234 567 89 10

很酷不是么?判断文件结束、移动文件指针之类的苦工都有 istream_iterator 代劳了。

———————————————————————–

其它算法配合 iterator

计算文件行数:

    int line_count =

        count(istreambuf_iterator<char>(ifs.rdbuf()),

              istreambuf_iterator<char>(),

              ‘n’);       

当然确切地说,这是在计算文件中回车符的数量,同理,你也可以计算文件中任何字符的数量,或者某个 token 的数量:

    int token_count =

        count(istream_iterator<string>(ifs),

              istream_iterator<string>(),

              "#include");       

注意上面计算的是 “#include” 作为一个 token 的数量,如果它和其他的字符连起来,是不算数的。

————————————————————————
Manipulator

Manipulator 是什么?简单的说,就是一个接受一个 stream 作为参数,并且返回一个 stream 的函数,比如上面的 unskipws ,它的定义是这样的:

  inline ios_base&

  noskipws(ios_base& __base)

  {

    __base.unsetf(ios_base::skipws);

    return __base;

  }

这里它用了更通用的 ios_base 。知道了这一点,你大概不会对自己写一个 manipulator 有什么恐惧感了,下面这个无聊的 manipulator 会忽略 stream 遇到第一个分号之前所有的输入(包括那个分号):

template <class charT, class traits>
inline std::basic_istream<charT, traits>&
ignoreToSemicolon (std::basic_istream<charT, traits>& s)
{
    s.ignore(std::numeric_limits<int>::max(), s.widen(‘;’));
    return s;
}

不过注意,它不会忽略以后的分号,因为 ignore 只执行了一次。更通用一点,manipulator 也可以接受参数的,下面这个就是 ignoreToSemicolon 的通用版本,它接受一个参数, stream 会忽略遇到第一个该参数之前的所有输入,写起来稍微麻烦一点:

struct IgnoreTo {
    char ignoreTo;
    IgnoreTo(char c) : ignoreTo(c)
    {}
};
   
std::istream& operator >> (std::istream& s, const IgnoreTo& manip)
{
    s.ignore(std::numeric_limits<int>::max(), s.widen(manip.ignoreTo));
    return s;
}

但是用法差不多:

    copy(istream_iterator<char>(ifs >> noskipws >> IgnoreTo(‘;’)),

         istream_iterator<char>(),

         ostream_iterator<char>(cout)

    );

其效果跟 IgnoreToSemicolon 一样。

关于Linux下C/C++程序编译

在编译之前我们需要在系统里安装G++ GCC,它们就是Linux下的C++/C的编译器。代码如下
代码:

sudo apt-get install build-essential

好,现在我们在文本编辑器里写一个C的简单的程序(好像所有学习C或者C++的书都会出现)
代码:

#include <stdio.h>
int main()
{
printf("Hello,World!n");
return 0;
}

现在存盘为Hello.c,打开你的终端,并在文件当前目录输入:
代码:

gcc Hello.c -o hello   

编译时可能会出现如下警告:no newline at and of file ,只有在文件结尾添加一个新行就好了。
然后在终端中输入 ./hello ,你就能在终端中看到程序运行结果了。

下面来说下C++是如何编译的
写程序(不用我多说了吧)
代码:

#include <iostream>
using namespace std;
int main()
{
cout<<"Hello,World!n"<<endl;
return 0;
}

存盘为Hello.cpp
使用gcc编译??? 不对,这里我们使用g++来编译C++程序
代码:

g++ Hello.cpp -o hello

编译多个文件我们怎么办??? 来看下面出了三个文件Hello.h, Hello.cpp, MyFirst.cpp
代码:

//file_NO1:Hello.h
class Hello {
Hello();
void Display();
}
//file_NO2:Hello.cpp
#include <iostream>
#include "Hello.h"
using namespace std;
Hello::Hello()
{
}
Hello::Display()
{
cout<<"Hello,World!n"<<endl;
}
//file_NO3:MyFirst.cpp
#include <iostram>
#include "Hello.cpp"
int main()
{
Hello theHello;
theHello->Display();
return 0;
}

在g++中有一个参数-c 可以只编译不连接,那么我们就可以按如下顺序编译文件,
代码:

g++ -c Hello.cpp -o Hello.o
g++ -c MyFirst.cpp -o MyFirst.o
g++ MyFirst.o hello.o -o MyFirst

你是否会问,如果是一个项目的话,可能会有上百个文件,这样的编译法,人不是要累死在电脑前吗,或者等到你编译成功了,岂不是头发都白了,呵呵,所以我们要把上述的编译过程写进以下一个文本文件中:
Linux下称之为makefile
[code]
#这里可以写一些文件的说明
MyFirst: MyFirst.o hello.o
g++ MyFirst.o hello.o -o MyFirst
Hello.o:Hello.cpp
g++ -c Hello.cpp -o Hello.o
MyFirst.o:MyFirst.cpp
g++ -c MyFirst.cpp -o MyFirst.o
[code]
存盘为MyFirst,在终端输入:make MyFist ,程序出现了错误可是所有程序员共同的敌人,在编写程序时我们应该尽量的去避免错误 的出现,不过编写的时候再怎么都不可避免的出现这样那样的错误,对程序进行必要的调试是一个好主意,那我们怎么来调试程序呢,看下面:
[code]
gdb ./文件名
[/code]
以下为调试状态下的可以用到的命令(可以仅输入单词的输入,如break可简为b),尖括号中为说明
[code]
list <显示源代码>
break 行号 <设置断点>
run <运行程序>
continue <继续从断点处执行>
print 变量 <调试时查看变量的值>
del 行号 <删除断点>
step <单步执行,可跟踪到函数内部>
next <单步执行,不可跟踪到函数内部>
quit <退出>
[/code]