置顶随笔

[置顶]资料分享声明

       鉴于网上找资料是件痛苦的,所以我把我自己的一些电子书,以及下载的一些小程序放在了邮箱里,跟大家分享,仅大家学习交流(这些资料一般已经在网上广为流传,我想应该没有触及版权的问题吧,呵呵)。大家有需要的可以去邮箱去下,目前只放了一部分,以后会陆续添加邮箱地址和密码如下:
账号:percyph1@163.com
密码:xcc123456
如果大家有c++,openGL,密码学等等计算机方面的好资料,也可以发给我,我的邮箱是 percyph@163.com
大家也可以回帖要资料,如果有的话我会第一时间发上。
相信来我这儿的朋友都是有素质的,请不要删除和移动邮箱里的文件,谢谢!

目前已经上传的资料有:(以后会陆续更新)

   VC编程助手(小软件VC++ assistant,能使编程更方便)
   C++Primer3(电子书)
   glut函数说明(电子书)
   C++技能百练(经典算法).rar 
   ROAM地形算法演示程序.rar 
   OpenGL 参考手册
   c&c++深层探索 
   C++必知必会 
   VC6.0编程实例精解 
   高质量C++编程指南&编程新手真言&MFC类库详解 
   Windows程序设计 
   MFC类库详解.chm 
   C++ 数据结构第三版 
   C++ 数据结构第三版 
   程序员面试宝典&程序员超级开发宝典 
   c++和OpenGL函数手册 
   Essential C++中文版.pdf 
   Effective C++(电子书) 
   C++编程思想(电子书)

3.11号上传(kuafoo发的)
   Windows环境下32位汇编语言.chm(2.78M)
   深入浅出MFC
   深入浅出MFC第二版
  
另外最近几个月写的数据结构的程序也传上去了,有兴趣的朋友可以看看!

里面包括:

线性表——静态链表2009.7.30
线性表——链表的内部类实现2008.8
线性表——链表的友元类实现2008.8
线性表——双向链表2009.8.11
线性表——顺序表2009.8.3
线性表——友元模板类2009.8

约瑟夫问题——四种解法2009.8.11(数组,链表,循环链表等)
队列——队列的顺序表示循环队列2009.8.11
队列——链队列2009.8.11
栈——汉诺塔2009.8.6
栈——进制转换2009.8.6
栈——括号匹配2009.8.6
栈——模板链栈2009.8.3
栈——模板顺序栈2009.7
栈——顺序栈2009.8.6
栈——算术表达式求值2009.7.13
栈——行编辑2009.8.6
二叉树——二叉树的常见操作2009.9.3

2010.3.9 更新

树的应用—仿DOS文件夹管理程序

200位大数乘法.rar

200位大数加法.rar

连连看单机程序MFC

posted @ 2009-03-06 18:32 小虫虫 阅读(665) | 评论 (4)编辑 收藏

2010年10月7日

基于四叉树LOD的3D地形实现(OpenGL)

我自己的毕业设计的1.0版本. 采用四叉树LOD算法实现地形渲染.已经传至共享邮箱里,希望对学3D的朋友有帮助

posted @ 2010-10-07 23:26 小虫虫 阅读(1545) | 评论 (4)编辑 收藏

2009年5月14日

(转)质数算法大全,及C程序实现优化详解 (二) 筛选法

质数的定义

一个数,如果只有1和它本身两个因数,这样的数叫做质数,又称素数。

在上文 《素数算法大全,及C程序实现优化详解 (一) 试除法》中我们已经探讨了求解素数的一类算法,并且将试除法从最初的低效版本优化的高效的V2。那么,还有没有其它更佳算法呢?这就是下面三藏要和大家探讨的内容

合数过滤筛选法

算法描述:我们知道,素数N不能被2~(N-1)间的任何数整除;反过来看,只要能被2~(N-1)间的任何数整除的N,都不是素数。所以我们可以采用一个简单的排除法:就是对N以内的所有数,只要逐个去除值为2~(N-1)的倍数的数,剩下的就是素数。

C语言实现

// 合数过滤筛选法 Ver1 
// 参数:n 求解n以内(包括n)的素数
// 返回值:n以内素数个数
int CompositeNumFilterV1(int n)
{
 int i, j;
 // 素数数量统计
 int count = 0;
 // 分配素数标记空间,结合后文思考为何+1
 char* flag = (char*)malloc( n+1 );
 
 // 初始化素数标记
 for (i=2; i<=n; i++)
 {
  // 为什么*(p+i)要写成flag[i]呢?可读性更佳尔
  flag[i] = 1;
 }
 
 // 写程序要注意排版和留空,方便阅读,也可减少出错几率
 // 以2~(N-1)为因子过滤合数
 for (i=2; i < n; i++)
 {
  for (j=2; i*j <= n; j++)
  {
   // i*j是由i,j两整数相乘而得,显然不是素数
   flag[i*j] = 0;
  }
 }
 
 // 统计素数个数
 for (i=2; i<=n; i++)
 {
  // 其实if(flag)就其同样作用了,但这么写是有留言的
  // 请参阅《C语言程序设计常见错误剖析及解决之道》一文
  if (1 == flag[i]) count++;
 }
  
 // 因输出费时,且和算法核心相关不大,故略
 
 // 释放内存,别忘了传说中的内存泄漏
 free(flag);
 
 return count;
}

在上文给出的main函数中以不同参数调用CompositeNumFilterV1函数,得到执行结果如下:

[100000]以内素数个数:9592, 计算用时:15毫秒
[1000000]以内素数个数:78498, 计算用时:125毫秒
[5000000]以内素数个数:348513, 计算用时:2578毫秒
[10000000]以内素数个数:664579, 计算用时:6281毫秒

注:因程序是非独占性运行的,所以时间不是完全精确的,但基本能反映实情

显然,比上文中的试除法要快,而且谁都可以看到上例是一个未经优化的粗陋版本,好多地方是三藏故意采用比较低效做法,为了与后文的优化版比较,凸显优化之重要,也为了初学者记住别采用类似低效做法,下面我们开始优化之旅

优化分析

上面CompositeNumFilterV1函数存在的问题有:

  1. 在外层循环,需要一直执行到n-1吗?不要,因为n/2~n-1间的数显然不能整出n
  2. 在内层循环中重复使用i*j显然是低效的,考虑到计算机中加减运算速度比乘除快,可以考虑变乘法为加法
  3. 在循环修改flag过程中,其实有很多数会被重复计算若干次,比如6=2*3=3*2,会被重复置0,类似操作很多,所以我们得设法避免或减少flag重复置0

据上述分析,我们可将程序优化如下:

// 合数过滤筛选法 Ver2 
// 参数:n 求解n以内(包括n)的素数
// 返回值:n以内素数个数
int CompositeNumFilterV2(int n)
{
 int i, j;
 // 素数数量统计
 int count = 0;
 // 分配素数标记空间,明白+1原因了吧,因为浪费了一个flag[0]
 char* flag = (char*)malloc( n+1 );
 
 // 初始化素数标记,要高效点咯
 flag[2] = 1;
 // 注意是i<n不是上例中的i<=n了,理由自思
 for (i=3; i<n; i++)
 {
  flag[i++] = 1;
  // 偶数自然不是素数,直接置0好了
  flag[i] = 0;
 }
 // n为奇数
 if (n%2 != 0)
 {
  flag[n] = 1;
 }
 
 // 从3开始filter,因为2的倍数早在初始化时代就干掉了
 // 到n/2止的理由还要说吗
 for (i=3; i <= n/2; i++)
 {
  // i是合数,请歇着吧,因为您的工作早有您的质因子代劳了
  if (0 == flag[i]) continue;
  
  // 从i的2倍开始过滤,变乘法为加法 
  for (j=i+i; j <= n; j+=i)
  {
   flag[j] = 0;
  }
 }
 
 // 统计素数个数
 for (i=2; i<=n; i++)
 {
  if (flag[i]) count++;
 }
  
 // 因输出费时,且和算法核心相关不大,故略
 
 // 释放内存,别忘了传说中的内存泄漏
 free(flag);
 
 return count;
}

再来调用CompositeNumFilterV2得到执行结果:

[100000]以内素数个数:9592, 计算用时:n太小,时间精度不够
[1000000]以内素数个数:78498, 计算用时:31毫秒
[5000000]以内素数个数:348513, 计算用时:453毫秒
[10000000]以内素数个数:664579, 计算用时:1062毫秒
[100000000]以内素数个数:5761455, 计算用时:12973毫秒

哇哇,比昨天的试除发快了好多倍,可见算法的威力,值得好好学习,别说学算法没用咯。

上例着那个计算一亿以内的素数只要约13秒,应该算不错了,今天是否可以休息了呢?No,我们要追求极限!

int CompositeNumFilterV3(int n)
{
 int i, j;
 // 素数数量统计
 int count = 0;
 // 分配素数标记空间,明白+1原因了吧,因为浪费了一个flag[0]
 char* flag = (char*)malloc( n+1 );
 // 干嘛用的,请仔细研究下文
 int mpLen = 2*3*5*7*11*13;
 char magicPattern[mpLen];
 // 奇怪的代码,why,思考无法代劳,想!
 for (i=0; i<mpLen; i++)
 {
  magicPattern[i++] = 1;
  magicPattern[i++] = 0;
  magicPattern[i++] = 0;
  magicPattern[i++] = 0;
  magicPattern[i++] = 1;
  magicPattern[i] = 0;
 }
 for (i=4; i<=mpLen; i+=5)
  magicPattern[i] = 0;
 for (i=6; i<=mpLen; i+=7)
  magicPattern[i] = 0;
 for (i=10; i<=mpLen; i+=11)
  magicPattern[i] = 0;
 for (i=12; i<=mpLen; i+=13)
  magicPattern[i] = 0;
 
 // 新的初始化方法,将2,3,5,7,11,13的倍数全干掉
 // 而且采用memcpy以mpLen长的magicPattern来批量处理
 int remainder = n%mpLen;
 char* p = flag+1;
 char* pstop = p+n-remainder;
 while (p < pstop)
 {
  memcpy(p, magicPattern, mpLen);
  p += mpLen;
 }
 if (remainder > 0)
 {
  memcpy(p, magicPattern, remainder);
 }
 flag[2] = 1;
 flag[3] = 1;
 flag[5] = 1;
 flag[7] = 1;
 flag[11] = 1;
 flag[13] = 1;
 
 // 从17开始filter,因为2,3,5,7,11,13的倍数早被kill了
 // 到n/13止的,哈哈,少了好多吧
 int stop = n/13;
 for (i=17; i <= stop; i++)
 {
  // i是合数,请歇着吧,因为您的工作早有您的质因子代劳了
  if (0 == flag[i]) continue;
  
  // 从i的17倍开始过滤
  int step = i*2;
  for (j=i*17; j <= n; j+=step)
  {
   flag[j] = 0;
  }
 }
 
 // 统计素数个数
 for (i=2; i<=n; i++)
 {
  if (flag[i]) count++;
 }
  
 // 因输出费时,且和算法核心相关不大,故略
 
 // 释放内存,别忘了传说中的内存泄漏
 free(flag);
 
 return count;
}

再看CompositeNumFilterV3执行结果:

[1000000]以内素数个数:78498, 计算用时:15毫秒
[5000000]以内素数个数:348513, 计算用时:203毫秒
[10000000]以内素数个数:664579, 计算用时:515毫秒
[100000000]以内素数个数:5761455, 计算用时:6421毫秒

再次优化后速度提升了又一倍左右,三藏不禁有点满足了,睡觉也!

posted @ 2009-05-14 15:48 小虫虫 阅读(949) | 评论 (0)编辑 收藏

(转)素数算法大全,及C程序实现优化详解 (一) 试除法

转自:http://www.doforfun.net/article/20090504/543.htm
经常有初学者询问求解N内所有素数(质数)的问题,对此,网上的解答也很多,但很多要么不够专业,要么只有程序没有算法解析,所以三藏大厦对此问题做个小结,探讨一下求解素数的常见算法,同时给出相应的C语言程序及其解析。为了方便初学者理解,本文将从易到难阐述不同算法,高手可以直接看后面的高效算法

质数的定义

一个数,如果只有1和它本身两个因数,这样的数叫做质数,又称素数。 

试除判断法

算法描述:从上述定义可知,素数不能被1和它本身之外的数整除,所以,判断一个数x是否素数只要看它是否能被2~sqrt(x)间的数整除即可;而求N内所有素数则是循环重复上述过程。

C语言实现

#include <time.h>
#include <malloc.h>
#define N 100000
// 简单试除判断法 Ver1
int SimpleDivisionV1(int n)
{
 int i,j;
 // 素数数量统计
 int count = 0;
 // 分配存放结果的空间
 int* primes = (int*)malloc( sizeof(int)*n );
 
 // 2是素数谁都知道,不算了
 primes[count++] = 2;
 // 循环计算3~n间的数
 for (i=3; i<=n; i++)
 {
  // 为什么是sqrt(i),思考一下
  for (j=2; j<=sqrt(i); j++)
  {
   // i被j整除,显然不是素数了
   if (i%j == 0) break;
  }
  // i不能被2~sqrt(i)间的数整除,素数也
  if (j > sqrt(i))
  {
   primes[count++] = i;
  }
 }
 
 // 因输出费时,且和算法核心相关不大,故略
 
 // 释放内存,别忘了传说中的内存泄漏
 free(primes);
 
 return count;
}

void main()
{
 int count;
 clock_t start, end;
 // time函数不够精确,用clock凑合一下吧
 start = clock();
 count = SimpleDivisionV1(N);
 
 end = clock();
 printf("[%d]以内素数个数:%d, 计算用时:%d毫秒\n", N, count, end-start);
 getch(); 
}

计算结果:
[100000]以内素数个数:9592, 计算用时:468毫秒
[1000000]以内素数个数:78498, 计算用时:10859毫秒
[5000000]以内素数个数:348513, 计算用时:103560毫秒

噢噢,算算十万还行,百万就10秒多了,而且时间增长很快,这不行,得优化一下!

优化分析

仔细研究一下SimpleDivisionV1我们可以发现以下几个问题:

  1. 在循环条件中重复调用sqrt(i)显然是比较浪费时间的
  2. 判断素数,真的需要拿2~sqrt(i)间的所有整数去除吗?我们知道,合数都可以分解成若干质数,所以只要2~sqrt(i)间的质数不能整除i即可

根据上面两点,我们可将SimpleDivisionV1升级为SimpleDivisionV2,如下

 // 简单试除判断法 Ver2 
int SimpleDivisionV2(int n)
{
 int i, j, k, stop;
 // 素数数量统计
 int count = 0;
 // 分配存放结果的空间
 int* primes = (int*)malloc( sizeof(int)*n );
 
 // 2是素数谁都知道,不算了
 primes[count++] = 2;
 stop = count;
 // 循环计算3~n间的数
 for (i=3; i<=n; i++)
 {
  k = sqrt(i);
  // 在循环条件中重复调用sqrt是低效做法,故引入k
  while (primes[stop] <= k && stop < count)
   stop++;
  // stop干什么用,思考一下
  for (j=0; j<stop; j++)
  {
   if (i%primes[j] == 0) break;
  }
  // i不能被2~sqrt(i)间的素数整除,自然也不能被其他数整除,素数也
  if (j == stop)
  {
   primes[count++] = i;
  }
 }
 
 // 因输出费时,且和算法核心相关不大,故略
 
 // 释放内存,别忘了传说中的内存泄漏
 free(primes);
 
 return count;
}

然后将main中调用的函数替换为SimpleDivisionV2,在看一下执行结果:

[100000]以内素数个数:9592, 计算用时:46毫秒
[1000000]以内素数个数:78498, 计算用时:546毫秒
[5000000]以内素数个数:348513, 计算用时:3515毫秒
[10000000]以内素数个数:664579, 计算用时:8000毫秒

很开心的看到,经过优化,速度提高了几十倍,尤其是时间增长曲线的坡度变小了,N值越大,V2函数比V1的效率就越高

对于试除判断这种质数算法来说,三藏认为SimpleDivisionV2基本已经接近极限,不大可能有量级上的突破了,有兴趣的朋友可以自己进一步优化。初学者除了参看上述例子外,可以尝试做各种修改及细节优化,也可以将除法变乘法,多加练习是学习编程的好方法。

虽然,上例中V2已经比V1快了很多了,但随着N的增大,耗时还是不少,那么我们还有更好的方法吗?

posted @ 2009-05-14 15:46 小虫虫 阅读(2437) | 评论 (1)编辑 收藏

2009年4月1日

(转)gluPerspective和gluLookAt的关系

转自: http://hi.baidu.com/sunguangran/blog/item/ded90ced94779dd2b31cb11c.html

终于搞明白gluPerspective和gluLookAt的关系了

函数原型
gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)

一个一个来,首先得设置gluPerspective,来看看它的参数都表示什么意思
fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,
aspect,这个好理解,就是实际窗口的纵横比,即x/y
zNear,这个呢,表示你近处,的裁面,
zFar表示远处的裁面,

如果还没有理解就继续看,
我们知道,远处的东西看起来要小一些,近处的东西看起来会大一些,这就是透视原理
如下图所示



假设那两条线表示公路,理论上讲,它们的两条边是平行的,
但现实情况中,它们在远方(可以无限远)总要相交于一点,
实际线段AB的长度=CD的长度,只是在此例中使用了透视角,故会有如上的效果,是不是很接近现实的情况?

结合我们刚才这两个函数
zNear,眼睛距离近处的距离,假设为10米远,请不要设置为负值,OpenGl就傻了,不知道怎么算了,
zFar表示远处的裁面,假设为1000米远,
就是这两个参数的意义了,

再解释下那个"眼睛睁开的角度"是什么意思,
首先假设我们现在距离物体有50个单位距离远的位置,
在眼睛睁开角度设置为45时,请看大屏幕:


我们可以看到,在远处一个球,,很好玩哈,
现在我们将眼睛再张开点看,将"眼睛睁开的角度"设置为178
(180度表示平角,那时候我们将什么也看不到,眼睛睁太大了,眼大无神)


我们只看到一个点,,,,,,,,,,,,,,,,,,,,,,,,,,,
因为我们看的范围太大了,这个球本身大小没有改变,但是它在我们的"视界"内太小了,


反之,我们将眼睛闭小些,改为1度看看会出现什么情况呢?


在我们距离该物体3000距离远,"眼睛睁开的角度"为1时,我们似乎走进了这个球内,这个是不是类似于相机的焦距?

当我们将"透视角"设置为0时,我们相当于闭上双眼,这个世界清静了,

我们什么也看不到,,,,,,,,,



现在来看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

它共接受三对坐标,
分别为eye,center,up
故名思义,eye表示我们眼睛在"世界坐标系"中的位置,
center表示眼睛"看"的那个点的坐标,
最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可
球是画在世界坐标系的原点上的,即O(0,0,0)坐标上,我们的眼睛位于观察点A(0,0,100),Z轴向屏幕里看去的方向为负,屏幕外我们的位置,Z轴为正值,其实很好理解,即我们距离原点的距离,设置100,将观察到如下图所示的影像

如果我们向前或向后移动,则相应的图像会变大或变小,这里其实就是运用了透视原理,近处的物体大,远处的物体小,实际物体的大小是不变的,

同理改变center坐标(眼睛看去的那个点,可简单理解为视线的终点)也会影响球的大小,同样可以认为是改变了物体与观察点的距离所致,

最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可,我们指定0.1f或0.00001f异或1000.0f,效果是一样的,只要能表示方向即可,




以上理解了之后,来做一个测试
透视图不变,最远处仍为3000,近处为0.1

gluPerspective                            // 设置透视图
        (45,                            // 透视角设置为 45 度,在Y方向上以角度为单位的视野
        (GLfloat)x/(GLfloat)y,    // 窗口的宽与高比
        0.1f,                                // 视野透视深度:近点1.0f
        3000.0f                            // 视野透视深度:始点0.1f远点1000.0f
        );


将我们的观察点置于A(0,10,0),
将观察位置(视线终点)坐标置于(0,0,0)
然后在原点开始绘图,画一个V字形,并将Z轴的值从-1000递增加到+1000,增量为10,
代码如下

    glColor3f(0.5f, 0.7f, 1.0f);

    glBegin(GL_LINES);
        for(int i=-1000;i<=1000;i+=10)
        {
            glVertex3f(0,0,i);
            glVertex3f(10,10,i);

            glVertex3f(0,0,i);
            glVertex3f(-10,10,i);
        }
    glEnd();

F5运行效果如下图


上图证实了我们的推测











//---------------------------------------------
    //生成网络
    glColor3f(0.5f, 0.7f, 1.0f);
    int x=(int)(40*2);
   
    glBegin(GL_LINES);
            for(int i=-x;i<=x;i+=4)
            {
                glVertex3i(-x,0,i);
                glVertex3i(x,0,i);

                glVertex3i(i,0,x);
                glVertex3i(i,0,-x);
            }
    glEnd();

//生成球体
    GLUquadricObj * pObj;
    pObj = gluNewQuadric();
    gluQuadricDrawStyle(pObj,GLU_LINE);
    gluQuadricNormals(pObj,GLU_SMOOTH);

=============================================================
以下是个小总结:
1、模视矩阵(ModelView Matrix)的作用是将模型从局部坐标系变换到世界坐标系,并最终变换到视点坐标系中。它由模型变换矩阵和视点变换矩阵组成。
2、gluLookAt影响的是视点矩阵,它显式的标明了视点坐标系与世界坐标系的关系,即视点被安置在世界坐标系的哪个位置,视线的方向朝向何处。
3、gluPerspective用于规定视景体范围,与模视矩阵无关,它影响的是投影矩阵和规一化矩阵。投影矩阵的作用是使模型产生近大远小的效果,规一化矩阵是将模型的z值规一化到0~1之间。
4、在编程的时候,需要glMatrixMode来指定矩阵堆栈的类型,然后对该矩阵进行修改。
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   的作用是初始化模视矩阵,将坐标原点重新设置在世界坐标系的原点。之后的glTranslate、glScale、glRotate都会改变模视矩阵中的模型变换矩阵。而glLookAt则设置视点变换矩阵。它们共同作用,使得模型能在世界坐标系中正确安放,并能从合适的角度去观察。

posted @ 2009-04-01 11:03 小虫虫 阅读(3778) | 评论 (0)编辑 收藏

2009年3月31日

关于初始化列表的初始化顺序

      一个Vector模板类,开始的时候是这样写的:
template <class T>
class Vector
{
public:
    Vector(unsigned n=8):_size(n),_data(new T[_size]){}
   //.........
protected:
    T*       _data;
    unsigned _size;
};
结果一运行,机子就慢了,打开任务管理器,占内存超大。后来想起来初始化列表是按照成员变量的声明顺序初始化的,所以在构造函数里_data数组先被初始化,这时_size没被初始化,即_size还是个随机值,估计随机的很大,呵呵,比方说_size为1234567,于是就申请了1234567的内存。。。。
于是修改如下就OK了:
template <class T>
class Vector
{
public:
    Vector(unsigned n=8):_size(n),_data(new T[_size]){}
   //.........
protected:
    unsigned _size;//先声明_size,先初始化它
    T*       _data;
};

posted @ 2009-03-31 10:33 小虫虫 阅读(628) | 评论 (2)编辑 收藏

碰到命名空间的问题

       昨天写个类,碰到个问题,我这里用简单的例子说明,比方说写个学生类,性别用枚举来表示,然后有个获得性别的函数GetGender(),返回值类型为Gender。
class Student
{
enum Gender{MALE,FEMALE};
//...
Gender GetGender();
};
函数的实现如下
Gender Student::GetGender
{//...
}
结果出错。感觉挺莫名其妙的,呵呵。后来一琢磨,改成了
Student::Gender Student::GetGender
{//...
}
成功!!!!这个写法有意思.^_^    

posted @ 2009-03-31 10:25 小虫虫 阅读(249) | 评论 (0)编辑 收藏

2009年3月6日

资料分享声明

       鉴于网上找资料是件痛苦的,所以我把我自己的一些电子书,以及下载的一些小程序放在了邮箱里,跟大家分享,仅大家学习交流(这些资料一般已经在网上广为流传,我想应该没有触及版权的问题吧,呵呵)。大家有需要的可以去邮箱去下,目前只放了一部分,以后会陆续添加邮箱地址和密码如下:
账号:percyph1@163.com
密码:xcc123456
如果大家有c++,openGL,密码学等等计算机方面的好资料,也可以发给我,我的邮箱是 percyph@163.com
大家也可以回帖要资料,如果有的话我会第一时间发上。
相信来我这儿的朋友都是有素质的,请不要删除和移动邮箱里的文件,谢谢!

目前已经上传的资料有:(以后会陆续更新)

   VC编程助手(小软件VC++ assistant,能使编程更方便)
   C++Primer3(电子书)
   glut函数说明(电子书)
   C++技能百练(经典算法).rar 
   ROAM地形算法演示程序.rar 
   OpenGL 参考手册
   c&c++深层探索 
   C++必知必会 
   VC6.0编程实例精解 
   高质量C++编程指南&编程新手真言&MFC类库详解 
   Windows程序设计 
   MFC类库详解.chm 
   C++ 数据结构第三版 
   C++ 数据结构第三版 
   程序员面试宝典&程序员超级开发宝典 
   c++和OpenGL函数手册 
   Essential C++中文版.pdf 
   Effective C++(电子书) 
   C++编程思想(电子书)

3.11号上传(kuafoo发的)
   Windows环境下32位汇编语言.chm(2.78M)
   深入浅出MFC
   深入浅出MFC第二版
  
另外最近几个月写的数据结构的程序也传上去了,有兴趣的朋友可以看看!

里面包括:

线性表——静态链表2009.7.30
线性表——链表的内部类实现2008.8
线性表——链表的友元类实现2008.8
线性表——双向链表2009.8.11
线性表——顺序表2009.8.3
线性表——友元模板类2009.8

约瑟夫问题——四种解法2009.8.11(数组,链表,循环链表等)
队列——队列的顺序表示循环队列2009.8.11
队列——链队列2009.8.11
栈——汉诺塔2009.8.6
栈——进制转换2009.8.6
栈——括号匹配2009.8.6
栈——模板链栈2009.8.3
栈——模板顺序栈2009.7
栈——顺序栈2009.8.6
栈——算术表达式求值2009.7.13
栈——行编辑2009.8.6
二叉树——二叉树的常见操作2009.9.3

2010.3.9 更新

树的应用—仿DOS文件夹管理程序

200位大数乘法.rar

200位大数加法.rar

连连看单机程序MFC

posted @ 2009-03-06 18:32 小虫虫 阅读(665) | 评论 (4)编辑 收藏

struct和typedef struct

分三块来讲述:
1 首先:
      在C中定义一个结构体类型要用typedef:
        typedef struct Student
        {
            int a;
        }Stu;
于是在声明变量的时候就可:Stu stu1;
如果没有typedef就必须用struct Student stu1;来声明
这里的Stu实际上就是struct Student的别名。
另外这里也可以不写Student(于是也不能struct Student stu1;了)
        typedef struct
        {
            int a;
        }Stu;
但在c++里很简单,直接
        struct Student
        {
           int a;
        };
于是就定义了结构体类型Student,声明变量时直接Student stu2;
===========================================
2其次:
在c++中如果用typedef的话,又会造成区别:
       struct   Student  
       {  
          int   a;  
       }stu1;//stu1是一个变量  
       typedef   struct   Student2  
       {  
          int   a;  
        }stu2;//stu2是一个结构体类型  
使用时可以直接访问stu1.a
但是stu2则必须先   stu2 s2;
然后               s2.a=10;
===========================================
3 掌握上面两条就可以了,不过最后我们探讨个没多大关系的问题
如果在c程序中我们写:
       typedef struct  
       {
           int num;
           int age;
       }aaa,bbb,ccc;
这算什么呢?
我个人观察编译器(VC6)的理解,这相当于
       typedef struct  
       {
           int num;
           int age;
       }aaa;
       typedef aaa bbb;
       typedef aaa ccc;
也就是说aaa,bbb,ccc三者都是结构体类型。声明变量时用任何一个都可以,在c++中也是如此。但是你要注意的是这个在c++中如果写掉了typedef关键字,那么aaa,bbb,ccc将是截然不同的三个对象。

posted @ 2009-03-06 14:20 小虫虫 阅读(28411) | 评论 (20)编辑 收藏

2009年3月3日

(转)glut函数详解(13)--视频大小调整API

*再次声明"glut"函数详解系列转自:阿杰--江南暖冬
int glutVideoResizeGet(GLenum param);
返回glut视频大小调整的信息.
参数:
param:
  GLUT_VIDEO_RESIZE_POSSIBLE:如果底层支持视频大小调整,则返回非0值,否则返回0.如果返回0,则其他视频大小调整函数的调用将不起作用.
  GLUT_VIDEO_RESIZE_IN_USE
  GLUT_VIDEO_RESIZE_X_DELTA
  GLUT_VIDEO_RESIZE_Y_DELTA
  GLUT_VIDEO_RESIZE_WIDTH_DELTA
  GLUT_VIDEO_RESIZE_HEIGHT_DELTA
  GLUT_VIDEO_RESIZE_X
  GLUT_VIDEO_RESIZE_Y
  GLUT_VIDEO_RESIZE_WIDTH
  GLUT_VIDEO_RESIZE_HEIGHT
 
后面几个常量值在网上没有搜到解释.

//*******************************************************************************************
void glutSetupVideoResizing(void);
 
void glutStopVideoResizing(void);
 
void glutVideoResize(int x, int y, int width, int height);
 
void glutVideoPan(int x, int y, int width, int height);

我把glut的头文件中的所有函数都整理了一遍,只可惜 video resize sub-API中的几个函数网上都没有具体的介绍,本菜鸟也无能为力,幸好这些函数都不是常用的,我想一般用不着.除了和视频有关的API,前面几个帖子的内容已经基本把glut的所有函数都过了一遍,本专题也就算是完成了,以后如果找到相关资料,会把这里的补上,也希望达人能够指点一二.

posted @ 2009-03-03 15:41 小虫虫 阅读(807) | 评论 (0)编辑 收藏

(转)glut函数详解(12)--游戏模式API

所谓游戏模式其实就是一种全屏模式,这里可以对该模式下的屏幕显示方式进行简单设置.详见下面具体解释.
 
//*******************************************************************************************
void glutGameModeString(const char *string);
通过一个字符串对game mode(游戏模式,也即全屏模式)进行设置,即对屏幕进行设置.
参数:
string:一个指向字符串的指针,字符串的内容即是对屏幕的设置.字符串的格式如下所示:
  "W*H"
  "W*H:Bpp"
  "W*H@Rr"
  "W*H:Bpp@Rr"
  "@Rr"
  ":Bpp"
  "Bpp:@Rr"
(注:W:屏幕宽度,以像素单位;H:屏幕高度,以像素为单位;Bpp:每个像素的内存大小(位数);Rr:屏幕的刷新率.)
例子:
1.如果我们只关心屏幕大小(800*600)而不关心每个像素的内存占用和刷新频率,可以写成:
    glutGameModeString("800*600");
2.如果只想把每个像素的内存占用设置成32位,可以写成:
    glutGameModeString(":32");
3.如果只想把刷新率设置成75赫兹,可以写成:
    glutGameModeString("@75");
4.如果前三种情况都考虑,可以写成:
    glutGameModeString("800*600:32@75");
其他情况按照上面给出的字符串格式写出即可.
注:
  1.这个函数只是对硬件的请求,如果设置不合法,则将被忽略.
  2.这个函数并不返回错误值,如果要获得错误信息,则要用glutGameModeGet()函数.

//*******************************************************************************************
int glutEnterGameMode(void);

进入相应的game mode,即让glutGameModeString()的设置生效.

//*******************************************************************************************
void glutLeaveGameMode(void);

离开glutGameModeString()设置的game mode.

//*******************************************************************************************

int glutGameModeGet(GLenum mode);

检测设置的模式是否有效

参数:
mode:
  GLUT_GAME_MODE_ACTIVE:如果程序运行在game mode,则返回非0值,如果运行在窗口模式,则返回0.
  GLUT_GAME_MODE_POSSIBLE:判断glutAameModeString()的设置是否有效,如果有效则返回非0值,否则返回0.但是glut手册中有一个警告,即使这个设置是有效的,也不能保证屏幕设置可以一定成功生效.
  GLUT_GAME_MODE_WIDTH:返回屏幕的宽度.
  GLUT_GAME_MODE_HEIGHT:返回屏幕的高度.
  GLUT_GAME_MODE_PIXEL_DEPTH:返回当前模式下每个像素所占用的内存空间(位数).
  GLUT_GAME_MODE_REFRESH_RATE:返回实际的刷新率(单位赫兹).
  GLUT_GAME_MODE_DISPLAY_CHANGED:正如前面所说,不能保证屏幕显示模式一定根据设置发生改变,这个常量可以用来测试是否真的进入了game mode(先前是窗口模式下的情况下),如果先前已经是game mode,则可以用来测试设置是否发生改变.返回非0值表示进入了game mode或设置已经发生改变,否则返回0.

posted @ 2009-03-03 15:38 小虫虫 阅读(980) | 评论 (0)编辑 收藏

仅列出标题  下一页
<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

常用链接

留言簿(5)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜