博文

探讨全局变量的析构顺序(2007-09-29 23:48:00)

摘要:                朱金灿   前言:最近回答了网友一个问题,当然我不是C++高手,我仅是提出我的猜想和大家交流。      经典的C++的教科书都这样写着:全局对象在调用 main之前初始化, 在退出main之后析构。但是大家请看下面这样一个程序:   #include <cstdlib> #include <iostream> #include <conio.h> using namespace std;   class gb { public: gb::gb() { std::cout<<"start"<<std::endl; };   gb::~gb() { std::cout<<"end"<<std::endl; getch(); }; };   gb a;   int main() { std::cout<<"This is in main"<<std::endl; return 0; }        大家认为输出是什么呢?大家可能会说:这不是很简单吗? StartThis is in mainEnd         实际上事情并没有这么简单。在dev-c++-4.9.9.2的工程上,输出结果是顺理成章的: StartThis is in mainEnd 在VC6.0上建一个控制台工程,把代码拷贝进去,发现运行结果却是: StartThis is in main      当时很感疑惑,难道gb类对象a没有执行析构函数?思考了一会,决定试验一下。把代码稍为修改一下,把cout全部换为C语言的printf()函数,如下:   #include <cstd......

阅读全文(3293) | 评论:0

求一个数的质因数分解式(2007-08-22 23:14:00)

摘要:                        朱金灿                一个数的质因数分解式就是把一个数分为一个个质数因子,比如60,它的质因数分解式就是2 2 3 5 ,首先这几个数都是质数,其次它们相乘为60。看《算法设计与分析基础》,见到书上提到数的质因数分解式,便编了一个小程序实现求一个数的质因数分解式。算法思路是这样的: 1.       首先判断该数是否为质数,如果不是就进行分解,如果是就输出; 2.       分解步骤是这样的:使用循环从被分解数的平方根中开始相除,一旦相除余数为0,就分别对余数和商进行类似分解,退出循环。   很显然,这个算法要使用递归。   代码如下:   #include <iostream> using namespace std; #include <math.h> #include <conio.h>   // 判断一个数是否是素数 bool IsPrimeNum(int number) {     bool bIsPrimeNum = true;        for (int i = int(sqrt((double)number));i>1;i--)        {         if((number%i)==0)       ......

阅读全文(9571) | 评论:2

(转载)ASCII 表(2007-03-06 22:04:00)

摘要:转载地址:http://www.mcu123.com/new/Article_Show.asp?ArticleID=154 ASCII ( A merican S tandard C ode for I nformation I nterchange , 美国信息互换标准代码 )是基于罗马字母表的一套电脑编码系统。它主要用于显示现代英语 和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准 ISO 646 。 控制字符 Binary Decimal Hex 缩写 可以显示的表示法 名称/意义zgyh 0000 0000 0 00 NUL ? 空字符(Null) 0000 0001 1 01 SOH ? 标题开始 0000 0010 2 02 STX ? 正文开始 0000 0011 3 03 ETX ? 正文结束 0000 0100 4 04 EOT ? 传输结束 0000 0101 5 05 ENQ ? 请求 0000 0110 6 06 ACK ? 收到通知 0000 0111 7 07 BEL ? 响铃 0000 1000 8 08 BS ? 退格 0000 1001 9 09 HT ? 水平 制表符 0000 1010 10 0A LF ? 换行键 0000 1011 11 0B VT ? 垂直制表符 0000 1100 12 0C FF ? 换页键 0000 1101 13 0D CR ? 回车键 0000 1110 14 0E SO ? 不用切换(Shift键) 0000 1111 15 0F SI ? 启用切换(Shift键) 0001 0000 16 10 DLE ? 数据通讯换码 0001 0001 17 11 DC1......

阅读全文(2454) | 评论:0

应用全排序算法解决一道逻辑推理题(2007-03-03 16:14:00)

摘要:                      朱金灿          全排序算法就是列举一些字符的所有排列顺序的一种算法,比较典型的采用递归法。下面是一种简单的全排序算法。   void Swap(char* a, char* b) {// 交换a和b   char temp;  temp = *a;   *a = *b;   *b = temp; } void Perm(char list[], int k, int m) { //生成list [k:m ]的所有排列方式   int i;   if (k == m) {//输出一个排列方式     for (i = 0; i <= m; i++)       putchar(list[i]);     putchar('\n');   }   else // list[k:m ]有多个排列方式     // 递归地产生这些排列方式     for (i=k; i <= m; i++) {       Swap (&list[k], &list[i]);       Perm (list, k+1, m);       Swap (&list [k], &list [i]);     } } int main(int argc, char *argv[]){ char s[6]="01234"; Perm(s,0,4); return 0;}   算法作者:拉格浪日,来源:燕赵草叶风 2006-7-1   下面我简单地应用这个算法解决一道推理问题。该推理是这样的: 一天晚上,一对已婚夫妇,和他们的儿子女儿在家里发生了一起谋杀案,凶手、帮凶、被害人和目击者分别是家里的人。情况如下: (1)目击者和那个帮凶不是同一性别 (2)年龄最大的和目击者不是同一性别 (3)年龄最轻的和被害人不是同一性别 (4)帮凶比受害者大 (5)父亲是年龄最长者 (6)凶手不......

阅读全文(3699) | 评论:0

《深入浅出MFC》的一个例子的一点问题(2007-01-14 15:33:00)

摘要:                                   朱金灿     《深入浅出MFC》在第二章中说:虚函数表的内容是依据类中的虚函数声明次序,一一填入函数指针。派生类会继承基类的虚函数表(以及其它可以继承的成员),当 我们在派生类中改写虚函数时,虚函数表就受了影响:表中元素所指的函数地址 将不再是基类的函数地址,而是派生类的函数地址。 测试程序: #include <iostream.h>#include <stdio.h>class ClassA{public:int m_data1;int m_data2;void func1() { }void func2() { }virtual void vfunc1() { }virtual void vfunc2() { }};class ClassB : public ClassA{public:int m_data3;void func2() { }virtual void vfunc1() { }};class ClassC : public ClassB{public:int m_data1;int m_data4;void func2() { }virtual void vfunc1() { }}; void main(){cout << sizeof(ClassA) << endl;cout << sizeof(ClassB) << endl;cout << sizeof(ClassC) << endl;ClassA a;ClassB b;ClassC c;b.m_data1 = 1;b.m_data2 = 2;b.m_data3 = 3;c.m_data1 = 11;c.m_data2 = 22;c.m_data3 =......

阅读全文(2742) | 评论:0

使用穷举法解决0—1背包问题(2006-07-09 12:06:00)

摘要:                     朱金灿   问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。 设n个物品的重量和价值分别存储于数组w[ ]和v[ ]中,限制重量为tw。考虑一个n元组(x0,x1,…,xn-1),其中xi=0 表示第i个物品没有选取,而xi=1则表示第i个物品被选取。用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n元组,就可以得到问题的解。  显然,每个分量取值为0或1的n元组的个数共为2n个。而每个n元组其实对应了一个长度为n的二进制数,且这些二进制数的取值范围为0~2n-1。因此,如果把0~2n-1分别转化为相应的二进制数,则可以得到我们所需要的2n个n元组。 下面是我据此思路编的一个小程序。 #include <stdio.h> #include <math.h>   #define MAX 100                      // 限定最多物品数 /*将n化为二进制形式,结果存放到数组b中*/ void conversion(int n,int b[MAX]) {  int i; for(i=0;i<MAX;i++) { b[i] = n%2; n = n/2; if(n==0)break; }   }   void main() { int i,j,n,b[MAX],temp[MAX]; float tw,maxv,w[MAX],v[MAX],temp_w,temp_v; printf("please input n:\n"); scanf("%d",......

阅读全文(4659) | 评论:0

C 语言程序设计第6章习题答案(一)(2006-06-14 16:44:00)

摘要: 谭浩强的《C程序设计》第六章的两道习题答案。     6.3求Sn=a+aa+aaa+…+aa…a(n个a位数)的值并显示Sn,其中a、n由键盘输入。例如:a=1,n=3,则Sn=1+11+111=123;     a=2,n=4,Sn=2+222+2222=2468。   #include <stdio.h> #include <math.h>   long Calculate(int a,int n) {    int temp = 0;    int sum =0;    for(int i=0;i<n;i++)    {           temp = temp + a*int(pow(double(10),double(i)));           sum = sum +temp;    }    return sum; }     int main(void) {     printf("%d\n",Calculate(2,4));        return 0; }     改进设想:大数的存诸问题。比如结果超出了长整型的范围。     6.14 打印出下列图案。            *         * * *       * * * * *     * * * * * * *  * * * *......

阅读全文(3873) | 评论:0

用指向指针的指针的方法对n个整数排序并输出(2006-04-14 15:14:00)

摘要:一道编程题目:用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。整数和n在主函数中输入,最后在主函数中输出。我对该题的理解是:用交换地址的办法来达到交换元素的目的。   #include <stdio.h> #include <malloc.h>   void Sort(int **p, int times) {     int *temp; int i=0; int j=0;     for (i=0; i<times-1; i++)     {         for (j=i+1; j<times; j++)         {    /*当某元素大于它后面的元素,交换它们的地址*/            if (**(p+i) > **(p+j))             {                 temp = *(p+i);                 *(p+i) = *(p+j);                 *(p+j) = temp;      &n......

阅读全文(7299) | 评论:0

结构体的成员变量的对齐问题(2006-04-06 17:08:00)

摘要:结构体的大小是一个令人迷惑不解的问题,不信,我出一题让你算算看:   enum DataType{IntData,CharData,VcharData};   struct Item      {        char ItemNAme[30];          DataType ItemType;          char ItemDecr[50];          int  ItemLength;   };   在你使用sizeof之前你能知道它的大小吗?我想即使你用sizeof得出结果后,结果还是会让你大吃一惊的:怎么是这个?       一.为什么要对齐?   《Windows核心编程》里这样说:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。在最好的情况下,是两倍的时间,有时更长。       二.成员变量对齐的原理   我花了一个上午,看了一些资料,总算把这个问题搞明白了。下面我以一些例子说明结构体成员变量的对齐问题。   对于 struct s1 {   char a;   long int d; double c; };   这个结构体的大小是16。编译器默认的一般是8字节对齐。a的大小是1,它就按1字节对齐(因......

阅读全文(5190) | 评论:0

一个字符统计程序(2006-01-16 11:02:00)

摘要:           我编了一个程序,统计一段字符中的字母字符,数字字符、空格字符和其他字符的个数。程序运行环境:Windows2000, VC++6.0。程序如下:#include <stdio.h>void StatisticsSymbol2(char *pChar){    int i=0;    int  NumberCount=0,LetterCount=0,BlankCount=0,OtherCount=0;  // 初始化各个统计变量    for(i=0;pChar[i]!='\0';i++)    {  if(( pChar[i]>47 )&&( pChar[i]<58 ) )   //  假如是数字,数字计数加1  {      NumberCount++;      continue;  }  if( ( pChar[i]>64 && pChar[i]<91 ) ||( pChar[i]>96 && pChar[i]<123 ))/*  假如是字母,字母计数加1     */ {    LetterCount++;     continue;  }if ( pChar[i]==' ') // 假如是空格,空格计数加1{     BlankCount++;     contin......

阅读全文(4148) | 评论:0