博文
探讨全局变量的析构顺序(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;
}
大家认为输出是什么呢?大家可能会说:这不是很简单吗?
Start
This is in main
End
实际上事情并没有这么简单。在dev-c++-4.9.9.2的工程上,输出结果是顺理成章的:
Start
This is in main
End
在VC6.0上建一个控制台工程,把代码拷贝进去,发现运行结果却是:
Start
This is in main
&n......
求一个数的质因数分解式(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)
 ......
(转载)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......
应用全排序算法解决一道逻辑推理题(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
下面我简单地应用这个算法解决一道推理问题。该推理是这样的:
一天晚上,一对已婚夫妇,和他们的儿子女儿在家里发生了一起......
《深入浅出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) <......
使用穷举法解决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");
sca......
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 打印出下列图案。
*
* * *
* * * * *
* * * * * * *
* * * *......
用指向指针的指针的方法对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);
&nbs......
结构体的成员变量的对齐问题(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字节对齐(因......
一个字符统计程序(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
......