chaosuper85

C++博客 首页 新随笔 联系 聚合 管理
  118 Posts :: 0 Stories :: 3 Comments :: 0 Trackbacks

#


www.51voa.com

www.cnn.com

posted @ 2010-01-14 00:29 chaosuper 阅读(94) | 评论 (0)编辑 收藏

为什么会出现select模型?

先看一下下面的这句代码:
int iResult = recv(s, buffer,1024);
这是用来接收数据的,在默认的阻塞模式下的套接字里,recv会阻塞在那里,直到套接字连接上有数据可读,把数据读到buffer里后recv函数才会返 回,不然就会一直阻塞在那里。在单线程的程序里出现这种情况会导致主线程(单线程程序里只有一个默认的主线程)被阻塞,这样整个程序被锁死在这里,如果永 远没数据发送过来,那么程序就会被永远锁死。这个问题可以用多线程解决,但是在有多个套接字连接的情况下,这不是一个好的选择,扩展性很差。
再看代码:
int iResult = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
iResult = recv(s, buffer,1024);

这一次recv的调用不管套接字连接上有没有数据可以接收都会马上返回。原因就在于我们用ioctlsocket把套接字设置为非阻塞模式了。不过 你跟踪 一下就会发现,在没有数据的情况下,recv确实是马上返回了,但是也返回了一个错误:WSAEWOULDBLOCK,意思就是请求的操作没有成功完成。 看到这里很多人可能会说,那么就重复调用recv并检查返回值,直到成功为止,但是这样做效率很成问题,开销太大。

select模型的出现就是为了解决上述问题。

select模型的关键是使用一种有序的方式,对多个套接字进行统一管理与调度

看核心代码:(这里只给出服务端的)

while ( 1 )
{
// 初始化fdset
FD_ZERO( &fdsRead );

// 将server套接字添加到可读集合中
FD_SET( sockServer, &fdsRead );

// 调用select
select( 0, &fdsRead, NULL, NULL, &tv );

// 判断server套接字的状态,如果套接字还在可读集合中,
// 说明有数据可以读入,则建立套接字可以成功
if ( FD_ISSET( sockServer, &fdsRead ) )
{
sockAccept = accept( sockServer, (sockaddr*)&addr, &nLen );
// 有数据可读,进行相关处理
}

当然了,这里演示的只是最基础的select的用法。网络通信中的I/O复用的相关问题还很多,还需要慢慢学习与深入。
posted @ 2010-01-13 23:04 chaosuper 阅读(230) | 评论 (0)编辑 收藏

Ubuntu Apache-PHP-MySQL Server

  1. sudo apt-get install mysql-server-5.0 mysql-client-5.0
  2. sudo apt-get install apache2 php5 libapache2-mod-php5 php5-mysql libapache2-mod-auth-mysql

  3. 使用sudo a2enmod php5 enable php5模块

测试一下:

     sudo vi /var/www/test.php

posted @ 2010-01-13 22:44 chaosuper 阅读(87) | 评论 (0)编辑 收藏

  Ubuntu 在安装时,如同大部分 Linux 发行版一样,都会同时安装 GNU 版本的 Java。这个 Java 的实用程度太低,尤其对于开发人员来说,是没有太多用处的。在 Ubuntu 下,安装 SUN Java 是一件很容易的事情。第一步:

sudo apt-get install sun-java5-jdk

  安装完毕之后,选择默认 java:

sudo update-alternatives --config java

  然后配置环境变量:

sudo vim /etc/environment

  在其中添加如下两行:

CLASSPATH=/usr/lib/jvm/java-1.5.0-sun/lib
JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun

  保存退出。

  之后安装配置 Eclipse。安装很简单:

sudo apt-get install eclipse

虽然已经这时新安装的 java 已经成为系统默认的 jvm,但是 Eclipse 并不会用 update-alternative 设置的 jvm 来启动自身,而使用的是以前的 GNU Java。GNU Java 是 1.4.2 的实现,而且在性能上远不如 SUN 的实现。为了让 Eclipse 利用 SUN Java 启动,我们还需要继续配置。首先将 SUN Java 完完全全的设置为系统的默认 JDK:

sudo update-java-alternatives -s java-1.5.0-sun

  然后编辑 JVM 配置文件:

sudo vim /etc/jvm

  将文件中的

/usr/lib/jvm/java-1.5.0-sun

  这一行移动到配置块的顶部。由于 Eclipse 会忽略 Ubuntu 的通用 Java 设置(貌似一个 bug),我们需要继续编辑 Eclipse 的 java_home 文件:

sudo vim /etc/eclipse/java_home

  如同上面一样,将

/usr/lib/jvm/java-1.5.0-sun

  这一行移动到文件的顶部。所有的安装配置完成之后,Ubuntu 的 Java 开发平台就基本完备了。

posted @ 2010-01-13 22:31 chaosuper 阅读(149) | 评论 (0)编辑 收藏

Linux内核编译过程详解(kernel2.6.7)


 

花了几天才编译成功kernel2.6.7,其过程真可谓艰辛.古语有云:"苦尽甘来!"现在终于可以乐上一阵了.由于许多朋友对操作的顺序及某些重要的配置知之甚少或知之不详,往往病急乱投医.加之网上的信息多且烦杂,使得编译内核成功率不高,甚至造成原来的系统崩溃的也不在少数.我就是其中一个。 3ws9dt X  
   'abR"  
  其实,编译内核并不是一件难事.如果能按照正确的方法来操作,最多花上一个半小时就能搞定.是不是很受鼓舞呀! x!tem  
   Jj4f[7/@e  
  废话少说,现在我们马上开始.我原来的系统是redhat9.0,内核2.4.20-8,编译的内核2.6.7,仅供参考. 5 I4>QT.  
   p tw5BEh  
  共分为四部分:编译前准备->编译配置->编译过程->运行内核的常见问题 Gt2#h)[ ?  
   `!Q~dHN  
  一 编译前准备 :|1ELT`f  
   1'7rm$U!._  
  1)下载一份内核源代码,我下的是linux-2.6.7.tar.bz2,你可在如下地址下载它或者是更新的版本. XK;4y%=HZ  
   Lx{BLbBI  
  http://kernel.org/pub/linux/kernel/v2.6/ K# %_ c:  
   (v<x)g^+X  
  2) 下载最新版本的module-init-tools( "module-init-tools-3.0.tar.gz" and "modutils-2.4.21-23.src.rpm") g"&PSm4A  
   -^`7r$q|_  
  http://www.kernel.org/pub/linux/kernel/people/rusty/modules/module-init-tools-3.0.tar.gz QAA!>\F  
   S5{J8ot  
  http://www.kernel.org/pub/linux/kernel/people/rusty/modules/modutils-2.4.21-23.src.rpm qBjR,  
   &CnT&Ko  
  3)安装module-init-tools. 它会替代depmod [/sbin/depmod]和其他工具. ekoV7BD[  
   J/(&M#uny  
  tar -zxvf module-init-tools-3.0.tar.gz 7pL]H'd  
   v>E!/ZjHQ  
  cd module-init-tools-3.0 E,wE:o  
   (=J6CTH A  
  ./configure --prefix=/sbin V9Tiv  
   l[w)g-\Y  
  make Xl t_|lA>x  
   rV|s{mi  
  make install MFjlh  
   _(`(--je  
  ./generate-modprobe.conf /etc/modprobe.conf =[C[_4Z"&7  
   <03-|k&"  
  4)安装modutils-2.4.21-23.src.rpm. 你可能会看到"user rusty and group rusty not existing"的警告. 没关系,你只需强制安装就是了.如果你不对Redhat 9和Redhat 8做这几步, 你将会在"make modules_install"这一步时出现问题. .V9W!dqS  
   (gxes9$)i  
  rpm -i modutils-2.4.21-23.src.rpm (,f+]3r  
   cXD4 S  
  rpmbuild -bb /usr/src/redhat/SPECS/modutils.spec C-#Y  
   _E19U}  
  rpm -Fi /usr/src/redhat/RPMS/i386/modutils-2.4.21-23.i386.rpm niJ7_b   
   d2X8:Uve  
  5)解压缩内核源代码.把下载的源代码包放到目录/usr/src下,然后 FtsIzK E  
   9 | e  
  cd /usr/src b@{gOr`I4  
   Nh#uM6!  
  tar xvfj linux-2.6.7.tar.bz2 6V;^}Yb?H  
   6O h!E z|1  
  cd linux-2.6.7 '^,kwU5  
   OM 6 Kbi  
  二 编译配置 4r3SQxQiHj  
   kWn,Fy)r  
  在这一部分涉及几个重要模块的配置请,特别注意.一般用"make menuconfig"命令来配置内核. $02#psD   
   .Q'fP  
  输入以上命令后出现一个菜单界面,用户可以对需要的模块.下面着重讲几个重要的配置 ')C4~Zk1.  
   Xfu>t}W  
  1)文件系统 x.&#Ug  
   wE[~  
  请务必要选中ext3文件系统, Ww{4&w%  
   1C`wXmQM  
  File systems---> 9|{s: x  
   [b|8?+  
  [*] Ext3 journalling file system support X3F/J[S  
   _ 6Pxv  
  [*] Ext3 Security Labels qAs;~9<  
   TfGO9kO  
  [*] JBD (ext3) debugging support ]*->qkpx,  
   7yINrdpR{d  
  以上三项一定要选上,而且要内建(即标*). 这个非常重要,在配置完后一定要检查一下.config文件有没有"CONFIG_EXT3_FS=y"这一项. 如果不是"CONFIG_EXT3_FS=y"而是"CONFIG_EXT3_FS=m",你在运行内核时就会遇上以下错误: pivotroot: pivot_root(/sysroot,/sysroot/initrd) failed 3E}z  
   &zXnXx{  
  2)网卡驱动 n_A=8qFZX  
   :ckmHqFPa  
  请务必把自己网卡对应的驱动编译进内核,比较普遍的网卡是realtek 8139,以下就是这种网卡的配置,以供参考 .;z&Tu  
   =3263$8'  
  Device Drivers---> /8cP1vby  
   "IAEp9_Q  
  Networking support---> a@V3?("  
   }h|=loeJ  
  Ethernet (10 or 100Mbit) ---> r7K1 ?(U\  
   $ \%2_kH  
  <*> RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL) > 0"$% W  
   .7~T(~uK  
  <*> RealTek RTL-8139 PCI Fast Ethernet Adapter support z^]$Wj7?  
   wu-'wBdz  
  3)声卡驱动 Jj.MP .  
   Ay;f76  
  也要选择自己声卡对应的驱动编译进内核,比较普遍的声卡是i810_audio,以下就是这种声卡的配置,以供参考 <s1i7X\YY  
   Tpe9=UO  
  Device Drivers ---> }&r>rM"  
   \'FxG  
  Sound ---> 3$k9GuA  
   xLyXJm E,  
  <*> Sound card support  @h;PO  
   E/~MfLI  
  Advanced Linux Sound Architecture ---> k+kYnwV~  
   p|iua-'y  
  <*> Advanced Linux Sound Architecture |O;K2  
   %-RaZ6z  
  <*> Sequencer support 4 PIj  
   2~`ssYy!#s  
  < > Sequencer dummy client #_X=:  
   $1k*V|t*  
  <*> OSS Mixer API Zd WDv`ZB0  
   ?U)J2.oz-  
  <*> OSS PCM (digital audio) API[*] OSS Sequencer API fP-8\!D  
   =%t 1m  
  <*> RTC Timer support MAGUM '\  
   ?sf4  
  PCI devices ---> ds|B o?  
   5.IdfiY  
  <*> Intel i8x0/MX440, SiS 7012; Ali 5455; NForce Audio; AMD768/8111 PI"(D >>A  
   m#Pirrd  
  Open Sound System ---> ZR yQ1-`  
   oB`OhJB  
  < > Open Sound System (DEPRECATED) !I(sd<;^N  
   L@7qd@b  
  以上三项配置关系到新内核能否正常运行,请备加注意.其他的配置如果不是很了解,大可以按默认的选择. 5N'I#j HE  
   8\B6R*O  
  三 编译 zZaKI i0  
   PE}|j]O  
  按如下命令编译,大概需要一个多小时,大可以好好放松一下 ZX{A/N(=  
   YljRJXqC  
  make bzImage ~VuL4"N^`  
   >[Rs{(:_A  
  make modules #hkwHs3\  
   sQ@&~'O^  
  make modules_install P PyOzWC  
   (G>aeL 2  
  make install LX^[W;*`]  
   YvDG1A5J  
  运行新内核之前,请检查一下/boot/grub/grub.conf的内容,下面的配置可作参考 K~auYMT  
   oc |E@Y@xP  
  # grub.conf generated by anaconda ZBNWz9|0O  
   ]Y,.fg>:>  
  # <YsF!  
   Hy$:t8usu  
  # Note that you do not have to rerun grub after making changes to this file  B r$.  
   d_Zw,:~Z  
  # NOTICE: You have a /boot partition. This means that ! j8 b 7%  
   <fW9OxVy  
  # all kernel and initrd paths are relative to /boot/, eg. Cs2-tb~`  
   zHn Z'\bC  
  # root (hd0,0) g=opr``  
   Uyl9V(r6  
  # kernel /vmlinuz-version ro root=/dev/hdc3 { _h<<  
   d5^d4:jY  
  # initrd /initrd-version.img 22t&OgZ%  
   @%{ xp@m  
  #boot=/dev/hdc ^_,)Bqv^-  
   a ~_ve_LRW  
  default=1 |2ACN'1Jc  
   ;y)Qwf  
  timeout=10 W6R$u/*  
   I"[OKZ~#  
  splashimage=(hd0,0)/grub/splash.xpm.gz U!D&^oRu9  
   Ln^:+w)  
  title Red Hat Linux (2.6.7) R1 .G=(=(d  
   AlPZpN  
  root (hd0,0) 4[=v *,  
    "R5 gY  
  kernel /vmlinuz-2.6.7 ro root=LABEL=/ # Roy9v/  
   p{T :z  
  initrd /initrd-2.6.7.img d{'d?;f  
   f5Gx^^R6  
  title Red Hat Linux F}W)9>z  
   r*+:  
  root (hd0,0) ?nr35 )  
   mWRb"TT@[  
  kernel /vmlinuz-2.4.20-8 ro root=LABEL=/ c:}}=#:  
   f6O2fnK%  
  initrd /initrd-2.4.20-8.img &Sl&q]C  
   RG%  
  四 运行内核的常见问题 q%v'Vw'  
   7:"`4^ ;  
  1)RPM问题 53SWi:S-C  
   !a=]&|I  
  进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误: SXf$!  
   *=4n6O8  
  rpmdb: unable to join the environment lgmLP)7n/  
   @ ;Fapu  
  error: db4 error(11) from dbenv->open: Resource temporarily unavailable XAN&q_tLG  
   >G5R0v FJ  
  error: cannot open Packages index using db3 - Resource temporarily unavailable (11)  ##=5  
   A"~jEC= Q  
  error: cannot open Packages database in /var/lib/rpm 3evO9(_I!  
   _mF,J l  
  no packages sN/L;0z  
   )mNPNWw]  
  解决方法是执行“export LD_ASSUME_KERNEL =2.2.25”命令,也可以将其写入/etc/bashrc。 + =;<zt6t  
   y)j$6M$9L2  
  2)Sound问题 8 9}jlF^(  
   >Ud[  
  声音部分的模块名也改变了。我的笔记本原来的声卡驱动是i810_audio,现在已改为snd-intel8x0。因此需要把下面的内容添加到/etc/modprobe.conf中: >+;a3};*C4  
   )4< ng;  
  alias char-major-14 soundcore \`u@7J  
   =mn&YipF  
  alias sound snd-intel8x0 <v]3i%E  
   [nd-uN  
  alias sound-slot-0 snd-intel8x0 _NrCGtY6  
   gx@{D=X 8  
  alias snd-card-0 snd-intel8x0 /UfYn~t'c  
   --~H!HMoSQ  
  alias sound-service-0-0 snd-mixer-oss } {62GSVI  
   m 0<6 p7  
  alias sound-service-0-1 snd-seq-oss =zRV}6@5  
   H1QZ5RIv#  
  alias sound-service-0-3 snd-pcm-oss |GCdxtR$j  
   2`]C6 '  
  alias sound-service-0-8 snd-seq-oss :=.,V+e!i{  
   Q`s?UB\7p  
  alias sound-service-0-12 snd-pcm-oss 55#s<,O  
   V-/!A((c  
  install snd-intel8x0 /sbin/modprobe --ignore-install sound-slot-0 && @%>2 {+8  
   U\V)`eaNu  
  { /bin/aumix-minimal -f /etc/.aumixrc -L >/dev/null 2>&1; /bin/true; } QOCe4C-x|p  
   E5d/8-  
  remove snd-intel8x0 #{2$',  
   ~@ D10r%  
  { /bin/aumix-minimal -f /etc/.aumixrc -S >/dev/null 2>&1; /bin/true; }; zj7+Ac/[  
   }^yu^rTY  
  /sbin/modprobe -r --ignore-remove sound-slot-0 [)M;sHE46  
   x'"~NX i  
  然后执行“modprobe sound”加载声音模块,并使用下列命令检验声卡驱动: kU=S?G=  
   n%x0t!JU  
  #cat /proc/asound/cards Y. 7V/t6  
   );Y>OV  
  显示结果如下: > HzXf C  
   -#v,T$ae   
  0 [SI7012]: ICH - SiS SI7012 .[p_ '2gi  
   :]Z6e1Fia#  
  SiS SI7012 at 0xdc00, irq 11 !-fWtA~  
   DXM_PP>w$a  
  3)VMware问题 ; T@]:v #I  
   #f=F:"#H  
  解决方法是: ?ZHPOO%.  
   dh^,(  
  ◆ 将/usr/bin/vmware-config.pl中所有的“/proc/ksyms”替换为“/proc/kallsyms”。使用“sed”命令可以达到这个目的。 n9 =Ht  
   +J\.?Lv,]  
  ◆ 重新运行该脚本,使用内核头文件编译新的内核模块。在编译过程中如发生错误,应该进入/usr/lib/vmware/modules/source,使用下面的命令将vmnet.tar解包: 8rvNx~  
   {<=owK4?  
  #tar xvf vmnet.tar g(xuC@6.  
   itiX'ft  
  ◆ 进入vmnet-only目录修改bridge.c文件。将“atomic_add(skb->truesize, &sk->wmem_alloc);”修改为“atomic_add(skb->truesize, &sk->sk_wmem_alloc);”,并用类似的方式将“protinfo”改为“sk_protinfo”。 <z=06+-A#I  
   7,G2Q8_  
  ◆ 再次把vmnet-only目录用下面的命令重新打包为vmmon.tar: O'-)BY&-u  
   t.OU7b^:|  
  #tar cvf vmmon.tar v
posted @ 2009-12-12 14:36 chaosuper 阅读(155) | 评论 (0)编辑 收藏

30而立,对于大多数的中国男人来说,30岁是道坎,迈过这一步是成功,退后一步是悬崖,必须向前的时候,只能向前,而不是选择后退。所以,30岁的男人最有压力,面对生活、工作、学习,每时每刻都要提醒自己,该做什么,不该做什么,什么可以做,什么又不可以做,都要清醒。同样,也必须明白很多事。

1、要知道,眼睛一闭一睁,一天就过去了。

时间不停流,总是在不停的前行,所以,要懂得只争朝夕,真正从内心里明白眼睛一闭一睁的概念,好好的度过每一天,而不是碌碌无为的不知道为谁而活,也不知道自己想要干些什么。

2、要明白,最爱的人是谁,要好好的去爱。

一定要明白,谁是你最爱的人,谁是最爱你的人,要好好的理解爱,用心的去爱,让爱充满阳光,同样温暖你生活的每个瞬间,只有这样,你的幸福指数才会最高,最令人羡慕。

3、要知道,最重要的责任,要用心去生活。

要记得,人生最重要的不是挣钱,而是有责任,对身边的人要负责,对生活要负责,对工作要负责,责任意识让自己学着慢慢成熟,同样也可以改变一个人的理想和信念,让大家得到肯定。

4、要明白,不断的学习,让自己逐步提高。

活到老,学到老。总理说的没有错。人生苦短,但一定不要忘记学习,毕竟,在学习中不断的提高自己,才可以获得更大的成功。相信这一点,比什么都重要。

5、要知道,思考非常重要,学会改变自己。

要不断的去思考,发现问题及时解决问题,并在发现问题和解决问题的时候学会改变自己,让自己去适应社会和团队的发展,当然,适应并不是放弃自己主观能动性。

6、要明白,钱不是第一位,爱才是第一位。

有钱可以提高生活质量,但并不是提高爱的质量,爱是第一位的,钱不是第一位,只有充满爱的生活,钱才更有价值,没有了爱,有再多的钱一点用都没有,全是自私和永不满足的欲望而已。

7、要知道,逆境不可怕,可怕的是失去信心。

顺境中发挥出自己应有的能力当然重要,但更重要的是在逆境中学会坚强的面对现实,只有这样,才会更有信心的去坚持自己的理想,相信自己,什么都不可怕。

8、要明白,有份事业,为自己的所爱而奋斗。

要知道自己最需要什么,什么最适合自己,也许,在很多次艰难的决择中,会发现自己最需要的是什么,朝着自己的目标去奋斗,相信会有成功的那一天。

9、要明白,健康是第一位,要学会多运动。

多多的运动,保持一个好的身体状态,身体是革命的本钱,只有保证在健康的前提下,一切理想才可以去谈,所以不要总是自以为是,科学合理的运动,健康第一位。

10、要知道,眼睛一闭不睁,一辈子就过去了。

理解这句话的真正用意,就是不要太去计较得与失,要勇敢的面对现实,要学会理解和宽容,要学会放弃,要懂得舍得的意思,活的开开心心的最重要,有个好的心态,一辈子才活的有意义。

posted @ 2009-10-30 23:29 chaosuper 阅读(136) | 评论 (0)编辑 收藏

 1,事业永远第一

  虽然金钱不是万能的,但没有钱是万万不能的,虽然这句话很俗,但绝对有道理,所以30岁之前,请把你大部分精力放在你的事业上。

  2,别把钱看得太重

  不要抱怨自己现在工资低,银行存款4位数以下,看不到前途,现在要做的就是努力学习,即使你文凭再高,怎么把理论运用到实践还是需要一个很长的锻炼过程,社会永远是一所最博大的大学,它让你学到的知识远比你在学校学到的重要得多,所以同样,你也别太介意学历低.30岁之前靠自己能力买车买房的人还是极少。

  3,学会体谅父母

  别嫌他们唠叨,等你为人父了你就知道可怜天下父母心,在他们眼里你还是个孩子,但他们真的老了,现在得你哄他们开心了,也许只要你的一个电话,一点小礼物,就可以让他们安心,很容易做到。

  4,交上好朋友

  朋友对你一生都影响重大,不要去结识太多酒肉朋友,至少得有一个能在关键时刻帮助你的朋友,如果遇到这么一个人,就好好把握,日后必定有用,不管他现在是富还是穷。

5,别太相信爱情

  心中要有爱,但请别说也别相信那些琼瑶阿姨小说里面的山盟海誓,世上本无永恒,重要的是责任,但女人心海底针,心变了,一切都成枉然,你要做的就是该出手时就出手,该放手时别犹豫.30岁之前的爱情不是假的,但只是大多数人都没有能真正把握好的能力,所以学会量力而行。

  6,别担心至今还保留初吻

  爱情不在多而在精,别以为自己20多岁还没碰过女孩子就害怕自己永远找不到老婆.以后你会有很多机会认识女孩子,要知道这个社会虽然男人多于女人,但现实是女人其实比男人更担心这个问题.男人30一枝花,你在升值而不是贬值,成熟的爱情往往更美丽更长久,所以不要像疯狗一样看到女孩就想追,学会品味寂寞。

  7,不要沉迷于任何东西

  所谓玩物而丧志,网络游戏是你在出校门之前玩的,你现在没有多余的时间和精力花费到这上面,否则你透支的东西以后都得偿还.一个人要有兴趣,爱好,但请分清楚轻重。

  8,年轻没有失败

  不要遇到挫折就灰心,年轻人要时刻保持积极向上的态度.失败了,重来过;失去了,再争取别的。错过了,要分析,下次来,要把握;幼稚了,下次,成熟点。不要紧,会好的,哪怕到了极点,也不要放弃,相信一定可以挺过去。不要消极,会好的。曾经的错,过去了,总不能回味在过去。现在的,很好,累完了,很舒服。不要伤,总会有人在支撑你。

9,不要轻易崇拜或者鄙视一个人

  人都有偶像,但请拥有你自己的个性.不要刻意去模仿一个人,因为你就是你,是唯一的,独一无二的,要有自信.也不要全盘否定一个人,每个人是有价值的,如果你不能理解他,也请学会接受。

  10,要有责任心.

  不管你曾经怎样,但请从现在开始做一个正直的人.男人要有责任心,无论是工作还是生活上,一个有责任心的人才能让别人有安全感,才能让别人觉得你是一个值得信赖的人.我们不要懦弱,但请不要伤害爱你的人和你爱的人,尤其是善良的女孩,因为这个世界善良的女孩不多了,即使不想拥有,但也请让她保持她美丽的心。

  11,男人的外貌并不重要.

  不要为自己的长相身高而过分担心,一个心地善良,为人正直的男人远比那些空有英俊相貌,挺拔身材但内心龌龊的男人要帅得多.如果有人以貌取人,请不要太在意,因为你不用去为一个低级趣味的人而难过。

  12,学会保护身体

  不要以为现在抽烟喝酒,熬夜通宵也没什么事.那是因为你的身体正处于你一生的黄金时段.30岁以后你就能明白力不从心这个词的意义了,身体是革命的本钱,没有好的身体什么也做不了,所以要尽量让自己过有规律的健康生活。

13,别觉得一事无成.

  你现在还没有资格谈成功,当然如果你有千万资产的除外.一开始太固定的职业并不一定是好事,或许在不断的改行当中,你会学到更丰富的知识,而且可以挖掘出自己的潜能,找到最适合你的工作。

  14,请认真工作

  即使你现在的工作再怎么无聊再怎么低级,也请你认真去对待,要知道任何成功人士都是从最小的事做起,或许你现在学不到多么了不起的知识,但起码你要学会良好的工作态度和工作方法,这对以后很重要。

  15,请认真对待感情.

  不要羡慕那些换女人像换鞋一样的花花公子,逢场作戏的爱情只是让你浪费时间浪费精力,一个人最痛苦的不是找不到爱人,而是心中没有了爱,当你把我爱你3 个字变成你最容易说的一句话时,那么你在爱情的世界里已经很难找到真正的幸福了.爱情没有公平,总有一个人比对方付出得多,即使没有结果,也别觉得不值, 因为你的付出不光是为了她,也是为了你自己的爱,为爱付出是很可贵的,赞自己一下。

  16.请留一点童心

  在内心深处,哪怕只是一个很小的角落里,请保持一份童心,不是幼稚,但有的时候单纯一点会让你很快乐.所以不要太计较得失,生活本无完美。

posted @ 2009-10-30 23:17 chaosuper 阅读(80) | 评论 (0)编辑 收藏

一、引言

  计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。在本文中,我们将对计算几何常用的基本算法做一个全面的介绍,希望对您了解并应用计算几何的知识解决问题起到帮助。

二、目录

  本文整理的计算几何基本概念和常用算法包括如下内容:

  矢量的概念

  矢量加减法

  矢量叉积

  折线段的拐向判断

  判断点是否在线段上

  判断两线段是否相交

  判断线段和直线是否相交

  判断矩形是否包含点

  判断线段、折线、多边形是否在矩形中

  判断矩形是否在矩形中

  判断圆是否在矩形中

  判断点是否在多边形中

  判断线段是否在多边形内

  判断折线是否在多边形内

  判断多边形是否在多边形内

  判断矩形是否在多边形内

  判断圆是否在多边形内

  判断点是否在圆内

  判断线段、折线、矩形、多边形是否在圆内

  判断圆是否在圆内

  计算点到线段的最近点

  计算点到折线、矩形、多边形的最近点

  计算点到圆的最近距离及交点坐标

  计算两条共线的线段的交点

  计算线段或直线与线段的交点

  求线段或直线与折线、矩形、多边形的交点

  求线段或直线与圆的交点

  凸包的概念

  凸包的求法

三、算法介绍

  矢量的概念

  如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2。

  矢量加减法

  设二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量加法定义为: P + Q = ( x1 + x2 , y1 + y2 ),同样的,矢量减法定义为: P - Q = ( x1 - x2 , y1 - y2 )。显然有性质 P + Q = Q + P,P - Q = - ( Q - P )。

  矢量叉积

  计算矢量叉积是与直线和线段相关算法的核心部分。设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P × Q = x1*y2 - x2*y1,其结果是一个标量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。

  叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:

  若 P × Q > 0 , 则P在Q的顺时针方向。
  若 P × Q < 0 , 则P在Q的逆时针方向。
  若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。

  折线段的拐向判断

  折线段的拐向判断方法可以直接由矢量叉积的性质推出。对于有公共端点的线段p0p1和p1p2,通过计算(p2 - p0) × (p1 - p0)的符号便可以确定折线段的拐向:

  若(p2 - p0) × (p1 - p0) > 0,则p0p1在p1点拐向右侧后得到p1p2。

  若(p2 - p0) × (p1 - p0) < 0,则p0p1在p1点拐向左侧后得到p1p2。

  若(p2 - p0) × (p1 - p0) = 0,则p0、p1、p2三点共线。

  具体情况可参照下图:

   

  判断点是否在线段上

  设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:( Q - P1 ) × ( P2 - P1 ) = 0 且 Q 在以 P1,P2为对角顶点的矩形内。前者保证Q点在直线P1P2上,后者是保证Q点不在线段P1P2的延长线或反向延长线上,对于这一步骤的判断可以用以下过程实现:

  ON-SEGMENT(pi,pj,pk)

  if min(xi,xj) <= xk <= max(xi,xj) and min(yi,yj) <= yk <= max(yi,yj)

  then return true;

  else return false;

  特别要注意的是,由于需要考虑水平线段和垂直线段两种特殊情况,min(xi,xj)<=xk<=max(xi,xj)和min(yi,yj)<=yk<=max(yi,yj)两个条件必须同时满足才能返回真值。

  判断两线段是否相交

  我们分两步确定两条线段是否相交:

  (1)快速排斥试验

    设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。

  (2)跨立试验

    如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。具体情况如下图所示:

   

  在相同的原理下,对此算法的具体的实现细节可能会与此有所不同,除了这种过程外,大家也可以参考《算法导论》上的实现。

  判断线段和直线是否相交

  有了上面的基础,这个算法就很容易了。如果线段P1P2和直线Q1Q2相交,则P1P2跨立Q1Q2,即:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。

  判断矩形是否包含点

  只要判断该点的横坐标和纵坐标是否夹在矩形的左右边和上下边之间。

    
  判断线段、折线、多边形是否在矩形中

  因为矩形是个凸集,所以只要判断所有端点是否都在矩形中就可以了。

  判断矩形是否在矩形中

  只要比较左右边界和上下边界就可以了。

  判断圆是否在矩形中

  很容易证明,圆在矩形中的充要条件是:圆心在矩形中且圆的半径小于等于圆心到矩形四边的距离的最小值。

  判断点是否在多边形中

  判断点P是否在多边形中是计算几何中一个非常基本但是十分重要的算法。以点P为端点,向左方作射线L,由于多边形是有界的,所以射线L的左端一定在多边形外,考虑沿着L从无穷远处开始自左向右移动,遇到和多边形的第一个交点的时候,进入到了多边形的内部,遇到第二个交点的时候,离开了多边形,……所以很容易看出当L和多边形的交点数目C是奇数的时候,P在多边形内,是偶数的话P在多边形外。

  但是有些特殊情况要加以考虑。如图下图(a)(b)(c)(d)所示。在图(a)中,L和多边形的顶点相交,这时候交点只能计算一个;在图(b)中,L和多边形顶点的交点不应被计算;在图(c)和(d) 中,L和多边形的一条边重合,这条边应该被忽略不计。如果L和多边形的一条边重合,这条边应该被忽略不计。

    

  为了统一起见,我们在计算射线L和多边形的交点的时候,1。对于多边形的水平边不作考虑;2。对于多边形的顶点和L相交的情况,如果该顶点是其所属的边上纵坐标较大的顶点,则计数,否则忽略;3。对于P在多边形边上的情形,直接可判断P属于多边行。由此得出算法的伪代码如下:

    count ← 0;
    以P为端点,作从右向左的射线L; 
    for 多边形的每条边s
     do if P在边s上 
          then return true;
        if s不是水平的
          then if s的一个端点在L上
                 if 该端点是s两端点中纵坐标较大的端点
                   then count ← count+1
               else if s和L相交
                 then count ← count+1;
    if count mod 2 = 1 
      then return true;
    else return false;



  其中做射线L的方法是:设P'的纵坐标和P相同,横坐标为正无穷大(很大的一个正数),则P和P'就确定了射线L。

  判断点是否在多边形中的这个算法的时间复杂度为O(n)。

  另外还有一种算法是用带符号的三角形面积之和与多边形面积进行比较,这种算法由于使用浮点数运算所以会带来一定误差,不推荐大家使用。

  判断线段是否在多边形内

  线段在多边形内的一个必要条件是线段的两个端点都在多边形内,但由于多边形可能为凹,所以这不能成为判断的充分条件。如果线段和多边形的某条边内交(两线段内交是指两线段相交且交点不在两线段的端点),因为多边形的边的左右两侧分属多边形内外不同部分,所以线段一定会有一部分在多边形外(见图a)。于是我们得到线段在多边形内的第二个必要条件:线段和多边形的所有边都不内交。

  线段和多边形交于线段的两端点并不会影响线段是否在多边形内;但是如果多边形的某个顶点和线段相交,还必须判断两相邻交点之间的线段是否包含于多边形内部(反例见图b)。

   

  因此我们可以先求出所有和线段相交的多边形的顶点,然后按照X-Y坐标排序(X坐标小的排在前面,对于X坐标相同的点,Y坐标小的排在前面,这种排序准则也是为了保证水平和垂直情况的判断正确),这样相邻的两个点就是在线段上相邻的两交点,如果任意相邻两点的中点也在多边形内,则该线段一定在多边形内。

  证明如下:
 

  命题1:
    如果线段和多边形的两相邻交点P1 ,P2的中点P' 也在多边形内,则P1, P2之间的所有点都在多边形内。
    

  证明:
    假设P1,P2之间含有不在多边形内的点,不妨设该点为Q,在P1, P'之间,因为多边形是闭合曲线,所以其内外部之间有界,而P1属于多边行内部,Q属于多边性外部,P'属于多边性内部,P1-Q-P'完全连续,所以P1Q和QP'一定跨越多边形的边界,因此在P1,P'之间至少还有两个该线段和多边形的交点,这和P1P2是相邻两交点矛盾,故命题成立。证毕。

  由命题1直接可得出推论:
  推论2:
    设多边形和线段PQ的交点依次为P1,P2,……Pn,其中Pi和Pi+1是相邻两交点,线段PQ在多边形内的充要条件是:P,Q在多边形内且对于i =1, 2,……, n-1,Pi ,Pi+1的中点也在多边形内。

  在实际编程中,没有必要计算所有的交点,首先应判断线段和多边形的边是否内交,倘若线段和多边形的某条边内交则线段一定在多边形外;如果线段和多边形的每一条边都不内交,则线段和多边形的交点一定是线段的端点或者多边形的顶点,只要判断点是否在线段上就可以了。

  至此我们得出算法如下:

    if 线端PQ的端点不都在多边形内 
      then return false;
    点集pointSet初始化为空;
    for 多边形的每条边s
      do if 线段的某个端点在s上
           then 将该端点加入pointSet;
         else if s的某个端点在线段PQ上
           then 将该端点加入pointSet;
         else if s和线段PQ相交 // 这时候已经可以肯定是内交了
           then return false;
    将pointSet中的点按照X-Y坐标排序;
    for pointSet中每两个相邻点 pointSet[i] , pointSet[ i+1]
      do if pointSet[i] , pointSet[ i+1] 的中点不在多边形中
           then return false;
    return true;


  这个过程中的排序因为交点数目肯定远小于多边形的顶点数目n,所以最多是常数级的复杂度,几乎可以忽略不计。因此算法的时间复杂度也是O(n)。

  判断折线是否在多边形内

  只要判断折线的每条线段是否都在多边形内即可。设折线有m条线段,多边形有n个顶点,则该算法的时间复杂度为O(m*n)。

  判断多边形是否在多边形内

  只要判断多边形的每条边是否都在多边形内即可。判断一个有m个顶点的多边形是否在一个有n个顶点的多边形内复杂度为O(m*n)。

  判断矩形是否在多边形内

  将矩形转化为多边形,然后再判断是否在多边形内。

  判断圆是否在多边形内

  只要计算圆心到多边形的每条边的最短距离,如果该距离大于等于圆半径则该圆在多边形内。计算圆心到多边形每条边最短距离的算法在后文阐述。

  判断点是否在圆内

  计算圆心到该点的距离,如果小于等于半径则该点在圆内。

  判断线段、折线、矩形、多边形是否在圆内

  因为圆是凸集,所以只要判断是否每个顶点都在圆内即可。

  判断圆是否在圆内

  设两圆为O1,O2,半径分别为r1, r2,要判断O2是否在O1内。先比较r1,r2的大小,如果r1<r2则O2不可能在O1内;否则如果两圆心的距离大于r1 - r2 ,则O2不在O1内;否则O2在O1内。

  计算点到线段的最近点

  如果该线段平行于X轴(Y轴),则过点point作该线段所在直线的垂线,垂足很容易求得,然后计算出垂足,如果垂足在线段上则返回垂足,否则返回离垂足近的端点;如果该线段不平行于X轴也不平行于Y轴,则斜率存在且不为0。设线段的两端点为pt1和pt2,斜率为:k = ( pt2.y - pt1. y ) / (pt2.x - pt1.x );该直线方程为:y = k* ( x - pt1.x) + pt1.y。其垂线的斜率为 - 1 / k,垂线方程为:y = (-1/k) * (x - point.x) + point.y 。

  联立两直线方程解得:x = ( k^2 * pt1.x + k * (point.y - pt1.y ) + point.x ) / ( k^2 + 1) ,y = k * ( x - pt1.x) + pt1.y;然后再判断垂足是否在线段上,如果在线段上则返回垂足;如果不在则计算两端点到垂足的距离,选择距离垂足较近的端点返回。

  计算点到折线、矩形、多边形的最近点

  只要分别计算点到每条线段的最近点,记录最近距离,取其中最近距离最小的点即可。

  计算点到圆的最近距离及交点坐标

  如果该点在圆心,因为圆心到圆周任一点的距离相等,返回UNDEFINED。

  连接点P和圆心O,如果PO平行于X轴,则根据P在O的左边还是右边计算出最近点的横坐标为centerPoint.x - radius 或 centerPoint.x + radius。如果PO平行于Y轴,则根据P在O的上边还是下边计算出最近点的纵坐标为 centerPoint.y -+radius或 centerPoint.y - radius。如果PO不平行于X轴和Y轴,则PO的斜率存在且不为0,这时直线PO斜率为k = ( P.y - O.y )/ ( P.x - O.x )。直线PO的方程为:y = k * ( x - P.x) + P.y。设圆方程为:(x - O.x ) ^2 + ( y - O.y ) ^2 = r ^2,联立两方程组可以解出直线PO和圆的交点,取其中离P点较近的交点即可。

  计算两条共线的线段的交点

  对于两条共线的线段,它们之间的位置关系有下图所示的几种情况。图(a)中两条线段没有交点;图 (b) 和 (d) 中两条线段有无穷焦点;图 (c) 中两条线段有一个交点。设line1是两条线段中较长的一条,line2是较短的一条,如果line1包含了line2的两个端点,则是图(d)的情况,两线段有无穷交点;如果line1只包含line2的一个端点,那么如果line1的某个端点等于被line1包含的line2的那个端点,则是图(c)的情况,这时两线段只有一个交点,否则就是图(b)的情况,两线段也是有无穷的交点;如果line1不包含line2的任何端点,则是图(a)的情况,这时两线段没有交点。

  计算线段或直线与线段的交点:

  设一条线段为L0 = P1P2,另一条线段或直线为L1 = Q1Q2 ,要计算的就是L0和L1的交点。

 1. 首先判断L0和L1是否相交(方法已在前文讨论过),如果不相交则没有交点,否则说明L0和L1一定有交点,下面就将L0和L1都看作直线来考虑。

 2. 如果P1和P2横坐标相同,即L0平行于Y轴

  a) 若L1也平行于Y轴,

    i. 若P1的纵坐标和Q1的纵坐标相同,说明L0和L1共线,假如L1是直线的话他们有无穷的交点,假如L1是线段的话可用"计算两条共线线段的交点"的算法求他们的交点(该方法在前文已讨论过);
    ii. 否则说明L0和L1平行,他们没有交点;

  b) 若L1不平行于Y轴,则交点横坐标为P1的横坐标,代入到L1的直线方程中可以计算出交点纵坐标;

 3. 如果P1和P2横坐标不同,但是Q1和Q2横坐标相同,即L1平行于Y轴,则交点横坐标为Q1的横坐标,代入到L0的直线方程中可以计算出交点纵坐标;

 4. 如果P1和P2纵坐标相同,即L0平行于X轴

  a) 若L1也平行于X轴,

    i. 若P1的横坐标和Q1的横坐标相同,说明L0和L1共线,假如L1是直线的话他们有无穷的交点,假如L1是线段的话可用"计算两条共线线段的交点"的算法求他们的交点(该方法在前文已讨论过);
    ii. 否则说明L0和L1平行,他们没有交点;

  b) 若L1不平行于X轴,则交点纵坐标为P1的纵坐标,代入到L1的直线方程中可以计算出交点横坐标;

 5. 如果P1和P2纵坐标不同,但是Q1和Q2纵坐标相同,即L1平行于X轴,则交点纵坐标为Q1的纵坐标,代入到L0的直线方程中可以计算出交点横坐标;

 6. 剩下的情况就是L1和L0的斜率均存在且不为0的情况

  a) 计算出L0的斜率K0,L1的斜率K1 ;

  b) 如果K1 = K2 

    i. 如果Q1在L0上,则说明L0和L1共线,假如L1是直线的话有无穷交点,假如L1是线段的话可用"计算两条共线线段的交点"的算法求他们的交点(该方法在前文已讨论过);
    ii. 如果Q1不在L0上,则说明L0和L1平行,他们没有交点。

  c) 联立两直线的方程组可以解出交点来

  这个算法并不复杂,但是要分情况讨论清楚,尤其是当两条线段共线的情况需要单独考虑,所以在前文将求两条共线线段的算法单独写出来。另外,一开始就先利用矢量叉乘判断线段与线段(或直线)是否相交,如果结果是相交,那么在后面就可以将线段全部看作直线来考虑。需要注意的是,我们可以将直线或线段方程改写为ax+by+c=0的形式,这样一来上述过程的部分步骤可以合并,缩短了代码长度,但是由于先要求出参数,这种算法将花费更多的时间。

  求线段或直线与折线、矩形、多边形的交点

  分别求与每条边的交点即可。

  求线段或直线与圆的交点:

  设圆心为O,圆半径为r,直线(或线段)L上的两点为P1,P2。

  1. 如果L是线段且P1,P2都包含在圆O内,则没有交点;否则进行下一步。

  2. 如果L平行于Y轴,

   a) 计算圆心到L的距离dis;
   b) 如果dis > r 则L和圆没有交点;
   c) 利用勾股定理,可以求出两交点坐标,但要注意考虑L和圆的相切情况。

  3. 如果L平行于X轴,做法与L平行于Y轴的情况类似;

  4. 如果L既不平行X轴也不平行Y轴,可以求出L的斜率K,然后列出L的点斜式方程,和圆方程联立即可求解出L和圆的两个交点;

  5. 如果L是线段,对于2,3,4中求出的交点还要分别判断是否属于该线段的范围内。

  凸包的概念

  点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。下图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。


   
 

  凸包的求法

  现在已经证明了凸包算法的时间复杂度下界是O(n*logn),但是当凸包的顶点数h也被考虑进去的话,Krikpatrick和Seidel的剪枝搜索算法可以达到O(n*logh),在渐进意义下达到最优。最常用的凸包算法是Graham扫描法和Jarvis步进法。本文只简单介绍一下Graham扫描法,其正确性的证明和Jarvis步进法的过程大家可以参考《算法导论》。

  对于一个有三个或以上点的点集Q,Graham扫描法的过程如下:

  令p0为Q中Y-X坐标排序下最小的点 
  设<p1,p2,...pm>为对其余点按以p0为中心的极角逆时针排序所得的点集(如果有多个点有相同的极角,除了距p0最远的点外全部移除
  压p0进栈S
  压p1进栈S
  压p2进栈S
    for i ← 3 to m
      do while 由S的栈顶元素的下一个元素、S的栈顶元素以及pi构成的折线段不拐向左侧
        对S弹栈
      压pi进栈S
    return S;

 

  此过程执行后,栈S由底至顶的元素就是Q的凸包顶点按逆时针排列的点序列。需要注意的是,我们对点按极角逆时针排序时,并不需要真正求出极角,只需要求出任意两点的次序就可以了。而这个步骤可以用前述的矢量叉积性质实现。

四、结语

  尽管人类对几何学的研究从古代起便没有中断过,但是具体到借助计算机来解决几何问题的研究,还只是停留在一个初级阶段,无论从应用领域还是发展前景来看,计算几何学都值得我们认真学习、加以运用,希望这篇文章能带你走进这个丰富多彩的世界。

posted @ 2009-10-27 22:26 chaosuper 阅读(402) | 评论 (0)编辑 收藏

当读者有一定c/c++基础
推荐的阅读顺序:
level 1
从<<essential c++>>开始,短小精悍,可以对c++能进一步了解其特性
以<<c++ primer>>作字典和课外读物,因为太厚不可能一口气看完

level 2
然后从<<effective c++>>开始转职,这是圣经,请遵守10诫,要经常看,没事就拿来翻翻
接着是<<exceptional c++>>,个人认为Herb Sutter主席大人的语言表达能力不及Scott Meyers总是在教育第一线的好
顺下来就是<<more effective c++>>和<<more exceptional c++>>,请熟读并牢记各条款
当你读到这里,应该会有一股升级的冲动了

level 3
<<insied the c++ object model>>看过后如一缕清风扫去一直以来你对语言的疑惑,你终于能明白compiler到底都背着你做了些什么了,这本书要细细回味,比较难啃,最好反复看几遍,加深印象
看完上一本之后,这本<<The design and evolution of c++>>会重演一次当年C++他爹在设计整个语言过程中的历程

level 4
<<the c++ standard library>>是stl的字典,要什么都可以查得到
学c++不能不学stl,那么首先是<<effective stl>>,它和圣经一样是你日常行为的规范
<<generic programming and the stl>>让你从oo向gp转变
光用不行,我们还有必要了解stl的工作原理,那么<<stl源码剖析>>会解决你所有的困惑

level 5
对于c++无非是oo和gp,想进一步提升oo,<<exeptional c++ style>>是一本主席这么多年的经验之谈,是很长esp的
一位stl高手是不能不去了解template的,<<c++ template>>是一本百科全书,足够你看完后对于gp游刃有余
<<modern c++ design>>是太过聪明的人写给明眼人看的

好书有很多,不能一一列举
以上我的读书经历,供各位参考。接下来的无非就是打怪练级,多听多写多看;boost、stl、loki这些都是利器,斩妖除魔,奉劝各位别再土法练钢了。

at last,无他,唯手熟尔。

忘了一本《thinking in C++》
也是经典系列之一



<<effective c++>>这本圣经的作者Scott Meyesr在给<<modern c++ design>>序言的时候高度的赞赏了Andrei同志的工作:C++社群对template的理解即将经历一次巨大的变化,我对它所说的任何事情,也许很快就会被认为是陈旧的、肤浅的、甚至是完全错的。
就我所知,template的世界还在变化,速度之快就像我1995年回避写它的时候一样。从发展的速度来看,我可能永远不会写有关template的技术书籍。幸运的是一些人比我勇敢,Andrei就是这样一位先锋。我想你会从此书得到很多收获。我自己就得到了很多——Scott Meyers September2000。

并且,Scott Meyers 在最近的Top5系列文章中,评价C++历史里面最重要5本书中、把Modern C++ Design列入其中,另外四本是它自己的effective c++、以及C++ Programming Language、甚至包括《设计模式》和《C++标准文档》。 
显然,Scott Meyers已经作为一个顶尖大师的角度承认了<<modern c++ design>>的价值。

并且调侃地说,可以把是否使用其中模板方法定义为,现代C++使用者和非现代C++使用者,并且检讨了自己在早期版本Effective对模板的忽视,最后重申在新版本Effective第七章节加入大量对模板程序设计的段落,作为对这次失误的补偿。

并且,在这里要明确的是<<modern c++ design>>并不是一本泛型编成的书,也不是一本模板手册。其中提出了基于策略的设计方法,有计划和目的的使用了模板、面向对象和设计模式。虽然Andrei本人对模板的研究世界无人能敌,但对其他领域的作为也令人赞叹。

任何做游戏的人都不能忽视OpenAL把,你在开发者的名单里能看到Loki的名字:)

最近很忙,无时间写文章,小奉献一下书籍下载地址。虽然经过验证,但是不感肯定各位一定能下:

<effective C++> 中文
http://www.itepub.net/html/ebookcn/2006/0523/40146.html
英文
http://dl.njfiw.gov.cn/books/C/Essential%20C++.chm
<c++ primer> 英文
http://www.vipbook.net/soft/2114.htm

<<effective c++>>英文
http://soft.studa.com/downinfo/19350.html

<exceptional c++> 英文
http://soft.studa.com/downinfo/19380.html

<more exceptional c++> 英文
http://soft.studa.com/downinfo/19377.html

<inside the C++ object Model>
http://dl.njfiw.gov.cn/books/C/Inside%20the%20C++%20Object%20Model.chm

< the design and evolution of c++ >
http://ebook.manboo.info/2006/11/19/the-design-and-evolution-of-c.html

< effective STL>
http://dl.njfiw.gov.cn/books/C/Effective%20STL.pdf

< the standard STL>
http://dl.njfiw.gov.cn/books/C/The%20C++%20Standard%20Library.chm

< moden C++ design>
http://dl.njfiw.gov.cn/books/C/Modern%20C++%20Design.chm

<exceptional c++ style>
http://cpp.ga-la.com/html/8/10/0510/71.htm

< c++ template >
http://www.itepub.net/html/ebookcn/2006/0429/7320.html

< generic programming and the STL >
http://www.jjhou.com/jjtbooks-generic-programming-and-the-stl.htm

posted @ 2009-10-22 09:04 chaosuper 阅读(185) | 评论 (0)编辑 收藏

真正的爱情,只有在平等的条件下产生。   
去追一个对你没感觉的女人,只会让她很烦,如果她碰巧很漂亮,有很多像你一样或者比你优秀的男人去追,那你一定不会有机会;即便上天给你了一个千载难逢的机会,并且还让你抓住了,那么最终,你还是会失去的。因为你的爱,当她不再需要的时候,或者遇到更好的男人的时候,就是负担。   
最惨的是碰到玩弄感情的女人,你一定死得很惨。   
女人拒绝男人,或者抛弃男人,根本理由只有一个,就是你达不到她的水平。   
在感情上,男人要主动,但是,主动之前先看看你自己够不够斤两,如果你不够她的水平,那就放弃吧!   
如果你观察过一个有一个以上男朋友的女人,你一定会发现,她最喜欢的一定是那个对她最冷淡的男人。   
所以说,爱人不如爱自己!   
你要是爱自己胜过别的任何人,你会专注于自己的事业,你就会开始有钱;你会注意自己的外表,你就会变的帅气;你会对自己充满信心,你会充满魅力。只要你懂得欣赏女人的心理,就会有很多的女人都来爱你。   
她们并不是爱你的钱,相信我。除非你是那种除了钱什么都没有的人,她们爱的确实是你这个人。你因此而取得了爱情中的优势。   
如果你取得了优势,你就有了选择的权力;你可以选择一个和你一样优秀的女人,自己做一个忠实的丈夫,所有人都会羡慕你们这对神仙眷属;你也可以选择一个自己心爱的但是并不如你的女人,这时你就不用那么辛苦地去追求她;你甚至可以去选择拥有无数的女人,社会不会谴责你,因为她们是心甘情愿的。   
知道为什么男人在二十岁的时候相信爱情,在三十岁的时候相信事业了吧。   
爱情是脆弱的,在现实面前根本不堪一击。世界上的确有很多的天荒地老,绝大多数是因为主人公都平凡得根本不会遭遇任何诱惑,幸运到能始终在一起。   
虚荣是爱情最大的敌人,第二就是长久的分离。小别胜新婚,长久的别离则是爱情的毒药。   
沉迷在爱情中的恋人指着月亮发誓天长地久,难道他们不知道,月亮本身都是会不断的在变么?月有阴晴圆缺,人有悲欢离合!   
想一想,十年之前,我们在哪里做什么?我们今天在做什么?十年之前,我们能想象到今天么?不能,所以我们也无法预料到十年以后。人,只有中年之后才能稳定下来,所以想承诺的话,到那时侯再承诺吧!

 

posted @ 2009-09-17 23:47 chaosuper 阅读(115) | 评论 (0)编辑 收藏

仅列出标题
共12页: First 2 3 4 5 6 7 8 9 10 Last