??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV无码久久精品狠狠爱浪潮,久久久久久夜精品精品免费啦,亚洲伊人久久综合影院 http://www.shnenglu.com/softko/淡薄名利,修nL?/description>zh-cn Wed, 07 May 2025 13:40:37 GMT Wed, 07 May 2025 13:40:37 GMT 60 数组与指针的区别 http://www.shnenglu.com/softko/archive/2013/02/19/197934.htmleircQ eircQ Tue, 19 Feb 2013 05:33:00 GMT http://www.shnenglu.com/softko/archive/2013/02/19/197934.html http://www.shnenglu.com/softko/comments/197934.html http://www.shnenglu.com/softko/archive/2013/02/19/197934.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/197934.html http://www.shnenglu.com/softko/services/trackbacks/197934.html C语言中对于下面的两种情况Q是否相同呢Q?/p>
char a[] = "abcdefg"Q?--------------1
char *p = "abcdefg";-----------------2
在谈到这些区别时Q应该先谈一下计机中对变量是如何存储的。从~译原理中我们知道,对于所有的变量他都会媄到一个符可中。ؓ了简化,q里l出一U最单的便于理解的符可Q?/p>
? 一个简单的W号表示?/p>
以上表格中a代表一个变量,0xffaa则ؓ变量a的内容的存储地址Qp代表另一个变量,0xffcc为变量p的内容的存储地址。对于数l型的变量和指针型的变量Q其地址代表的含义不同?/p>
对于数组a:
q个0xffaa地址是其存放数l内容的首地址了。对于a[i]的引用步骤如下:
步骤一、取出i的|他?xffaa相加Q?/p>
步骤二、取Zؓ(0xffaa+i)中的内容?/p>
对于指针p:
q个0xffcc地址是中存攄不是字符串的内容Q而是一个地址Q这个地址才是字符串的首地址Q对p[i]或者用指针表示*(p+i)的应用步骤如下:
步骤一、取?xffcc地址中的内容Q例如ؓ0xffdf;
步骤二、取出地址0xffdf中的内容?/p>
数组和指针的Ҏ如下图:
下面是在VC6.0下作的一个试验,通过q个试验大家可以看到Q虽然同q[]和通过*引用都一P但在内部处理的方法是不一L?/p>
#include "stdafx.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
int a[3]={1,2,3};
int *p =a;
printf("a:%d,&a:%d,a[0]:%d,*a:%d,p:%d,&p:%d,*p:%d,p[0]:%d",a,&a,
a[0],*a,p,&p,*p,p[0]);
return 0;
}
输出l果Q?/p>
a:1310580,&a:1310580,a[0]:1,*a:1,p:1310580,&p:1310576,*p:1,p[0]:1?/p>
׃面的分析可知Q如果在一个文件中定义了一个数lint maychar[100],那么下面的声明就是完全错误的?/p>
extern int *maychar;
q样的话Q在引用时他׃按照指针的方法来引用数组。正的声明应该是exter int maychar[];q里数组的大ƈ不重要。下面将指针与数l的区别用表格的形式列出如下Q?/p>
指针
数组
保存数据的地址
保存数据
间接讉K数据
直接讉K
通常用于动态数据结?/p>
通常用于存储固定数目数据cd相同的元?/p>
相关操作malloc(),free(){?/p>
隐式分配和删?/p>
同常指向匿名数据
自n即ؓ数据?/p>
? 指针与数l的区别
q要提醒一点的是Q?/p>
char a[] = "abcdefg"Q?--------------数组内容能修?字符数组)
char *p = "abcdefg";-----------------内容不能修改Q字W串帔RQ?/p>
在ANSI C中,初始化指针是所创徏的字W串时常量,被定义ؓ只读Q如果试N过指针修改q个字符串的|E序׃出现为定义的行ؓ?/p>
]]>新的一q_新的一天,新的气象。2Q1Q,我来也?/title> http://www.shnenglu.com/softko/archive/2012/01/20/164390.htmleircQ eircQ Thu, 19 Jan 2012 17:38:00 GMT http://www.shnenglu.com/softko/archive/2012/01/20/164390.html http://www.shnenglu.com/softko/comments/164390.html http://www.shnenglu.com/softko/archive/2012/01/20/164390.html#Feedback 1 http://www.shnenglu.com/softko/comments/commentRss/164390.html http://www.shnenglu.com/softko/services/trackbacks/164390.html 可以?012是{折的一q?br /> 我也开始思考自己?br /> 公司在{型,我也在{变?br /> 2012q的目标Q?br /> 一.控制自己?br /> 做自己对自己持箋受益的事情?br /> ?不断地学习。学习前人的l验Q避免前人的错误?br /> 看书Q学习技能,学习历史Q,观察周围的hQ思考?br /> ?认识自己。努力去做好自己。徏设自q原则。(每天思考) ?更加Ȁ情地ȝqz,去融入到生活Q工作中。真诚对待每一个h?br /> ]]> 各种排序法介绍 http://www.shnenglu.com/softko/archive/2011/06/17/148828.htmleircQ eircQ Fri, 17 Jun 2011 00:09:00 GMT http://www.shnenglu.com/softko/archive/2011/06/17/148828.html http://www.shnenglu.com/softko/comments/148828.html http://www.shnenglu.com/softko/archive/2011/06/17/148828.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/148828.html http://www.shnenglu.com/softko/services/trackbacks/148828.html 排序法是一U基本ƈ且常用的法。由于实际工作中处理的数量巨大,所以排序算法对法本n的速度要求很高?br /> 而一般我们所谓的法的性能主要是指法的复杂度Q一般用OҎ来表C。在后面我将l出详细的说明?br /> 对于排序的算法我惛_做一点简单的介绍Q也是给q篇文章理一个提UӀ?br /> 我将按照法的复杂度Q从单到难来分析法?br /> W一部分是简单排序算法,后面你将看到他们的共同点是算法复杂度为O(N*N)Q因为没有用word,所以无法打Z标和下标Q?br /> W二部分是高U排序算法,复杂度ؓO(Log2(N))。这里我们只介绍一U算法。另外还有几U算法因为涉及树与堆的概念,所以这里不于讨论?br /> W三部分cM动脑{。这里的两种法q不是最好的Q甚x最慢的Q,但是法本n比较奇特Q值得参考(~程的角度)。同时也可以让我们从另外的角度来认识q个问题?br /> W四部分是我送给大家的一个餐后的甜点——一个基于模板的通用快速排序。由于是模板函数可以对Q何数据类型排序(抱歉Q里面用了一些论坛专家的呢称Q? 现在Q让我们开始吧Q? 一、简单排序算? ׃E序比较单,所以没有加什么注释。所有的E序都给Z完整的运行代码,q在我的VC环境下运行通过。因为没有涉及MFC和WINDOWS的内容,所以在BORLAND C++的^C应该也不会有什么问题的。在代码的后面给Zq行q程C意Q希望对理解有帮助? 1.冒法: q是最原始Q也是众所周知的最慢的法了。他的名字的由来因ؓ它的工作看来象是冒Q? #include <iostream.h> void BubbleSort(int* pData,int Count) { int iTemp; for(int i=1;i<Count;i++) { for(int j=Count-1;j>=i;j--) { if(pData[j]<pData[j-1]) { iTemp = pData[j-1]; pData[j-1] = pData[j]; pData[j] = iTemp; } } } } void main() { int data[] = {10,9,8,7,6,5,4}; BubbleSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->10,9,7,8->10,7,9,8->7,10,9,8(交换3? W二轮:7,10,9,8->7,10,8,9->7,8,10,9(交换2? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9->8,7,10,9->7,8,10,9(交换2? W二轮:7,8,10,9->7,8,10,9->7,8,10,9(交换0? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 上面我们l出了程序段Q现在我们分析它Q这里,影响我们法性能的主要部分是循环和交换, 昄Q次数越多,性能p差。从上面的程序我们可以看出@环的ơ数是固定的Qؓ1+2+...+n-1? 写成公式是1/2*(n-1)*n? 现在注意Q我们给出OҎ的定义: 若存在一帔RK和v点n0Q当n>=n0Ӟ有f(n)<=K*g(n),则f(n) = O(g(n))。(呵呵Q不要说没学好数学呀Q对于编E数学是非常重要的!Q!Q? 现在我们来看1/2*(n-1)*nQ当K=1/2Qn0=1Qg(n)=n*nӞ1/2*(n-1)*n<=1/2*n*n=K*g(n)。所?n)=O(g(n))=O(n*n)。所以我们程序@环的复杂度ؓO(n*n)? 再看交换。从E序后面所跟的表可以看刎ͼ两种情况的@环相同,交换不同。其实交换本w同数据源的有序E度有极大的关系Q当数据处于倒序的情冉|Q?交换ơ数同@环一P每次循环判断都会交换Q,复杂度ؓO(n*n)。当数据为正序,不会有交换。复杂度为O(0)。ؕ序时处于中间状态。正是由于这?的原因,我们通常都是通过循环ơ数来对比算法? 2.交换法: 交换法的E序最清晰单,每次用当前的元素一一的同其后的元素比较ƈ交换? #include <iostream.h> void ExchangeSort(int* pData,int Count) { int iTemp; for(int i=0;i<Count-1;i++) { for(int j=i+1;j<Count;j++) { if(pData[j]<pData[i]) { iTemp = pData[i]; pData[i] = pData[j]; pData[j] = iTemp; } } } } void main() { int data[] = {10,9,8,7,6,5,4}; ExchangeSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->9,10,8,7->8,10,9,7->7,10,9,8(交换3? W二轮:7,10,9,8->7,9,10,8->7,8,10,9(交换2? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9->7,10,8,9->7,10,8,9(交换1? W二轮:7,10,8,9->7,8,10,9->7,8,10,9(交换1? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 从运行的表格来看Q交换几乎和冒一L。事实确实如此。@环次数和冒一样也?/2*(n-1)*nQ所以算法的复杂度仍然是O(n*n)。由于我们无法给出所有的情况Q所以只能直接告诉大家他们在交换上面也是一Lp糕Q在某些情况下稍好,在某些情况下E差Q? 3.选择法: 现在我们l于可以看到一点希望:选择法,q种Ҏ提高了一Ҏ能Q某些情况下Q? q种ҎcM我们Zؓ的排序习惯:从数据中选择最的同第一个g换,在从省下的部分中选择最的与第二个交换Q这样往复下厅R? #include <iostream.h> void SelectSort(int* pData,int Count) { int iTemp; int iPos; for(int i=0;i<Count-1;i++) { iTemp = pData[i]; iPos = i; for(int j=i+1;j<Count;j++) { if(pData[j]<iTemp) { iTemp = pData[j]; iPos = j; } } pData[iPos] = pData[i]; pData[i] = iTemp; } } void main() { int data[] = {10,9,8,7,6,5,4}; SelectSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->(iTemp=9)10,9,8,7->(iTemp=8)10,9,8,7->(iTemp=7)7,9,8,10(交换1? W二轮:7,9,8,10->7,9,8,10(iTemp=8)->(iTemp=8)7,8,9,10(交换1? W一轮:7,8,9,10->(iTemp=9)7,8,9,10(交换0? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->(iTemp=8)8,10,7,9->(iTemp=7)8,10,7,9->(iTemp=7)7,10,8,9(交换1? W二轮:7,10,8,9->(iTemp=8)7,10,8,9->(iTemp=8)7,8,10,9(交换1? W一轮:7,8,10,9->(iTemp=9)7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 遗憾的是法需要的循环ơ数依然?/2*(n-1)*n。所以算法复杂度为O(n*n)? 我们来看他的交换。由于每ơ外层@环只产生一ơ交换(只有一个最|。所以f(n)<=n 所以我们有f(n)=O(n)?br />所以,在数据较q时候,可以减少一定的交换ơ数? 4.插入法: 插入法较为复杂,它的基本工作原理是抽出牌Q在前面的牌中寻扄应的位置插入Q然后l下一? #include <iostream.h> void InsertSort(int* pData,int Count) { int iTemp; int iPos; for(int i=1;i<Count;i++) { iTemp = pData[i]; iPos = i-1; while((iPos>=0) && (iTemp<pData[iPos])) { pData[iPos+1] = pData[iPos]; iPos--; } pData[iPos+1] = iTemp; } } void main() { int data[] = {10,9,8,7,6,5,4}; InsertSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->9,10,8,7(交换1?(循环1? W二轮:9,10,8,7->8,9,10,7(交换1?(循环2? W一轮:8,9,10,7->7,8,9,10(交换1?(循环3? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9(交换0?(循环1? W二轮:8,10,7,9->7,8,10,9(交换1?(循环2? W一轮:7,8,10,9->7,8,9,10(交换1?(循环1? 循环ơ数Q?? 交换ơ数Q?? 上面l尾的行为分析事实上造成了一U假象,让我们认U算法是单算法中最好的Q其实不是,因ؓ其@环次数虽然ƈ不固定,我们仍可以用O?法。从上面的结果可以看出,循环的次数f(n)<= 1/2*n*(n-1)<=1/2*n*n。所以其复杂度仍为O(n*n)Q这里说明一下,其实如果不是Z展示q些单排序的不同Q交换次C?可以q样推导Q。现在看交换Q从外观上看Q交换次数是O(n)Q推导类似选择法)Q但我们每次要进行与内层循环相同ơ数?#8216;=’操作。正常的一ơ交换我?需要三?#8216;=’Q而这里显然多了一些,所以我们浪费了旉? 最l,我个为,在简单排序算法中Q选择法是最好的? 二、高U排序算法: 高排序法中我们将只介l这一U,同时也是目前我所知道Q我看过的资料中Q的最快的? 它的工作看v来仍然象一个二叉树。首先我们选择一个中间值middleE序中我们用数l中间|然后把比它小的放在左边,大的攑֜双Q具体的实现是从两边找,扑ֈ一对后交换Q。然后对两边分别使用q个q程Q最Ҏ的方?#8212;—递归Q? 1.快速排序: #include <iostream.h> void run(int* pData,int left,int right) { int i,j; int middle,iTemp; i = left; j = right; middle = pData[(left+right)/2]; //求中间? do{ while((pData[i]<middle) && (i<right))//从左扫描大于中值的? i++; while((pData[j]>middle) && (j>left))//从右扫描大于中值的? j--; if(i<=j)//扑ֈ了一对? { //交换 iTemp = pData[i]; pData[i] = pData[j]; pData[j] = iTemp; i++; j--; } }while(i<=j);//如果两边扫描的下标交错,停止(完成一ơ) //当左辚w分有?left<j)Q递归左半? if(left<j) run(pData,left,j); //当右辚w分有?right>i)Q递归叛_? if(right>i) run(pData,i,right); } void QuickSort(int* pData,int Count) { run(pData,0,Count-1); } void main() { int data[] = {10,9,8,7,6,5,4}; QuickSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } q里我没有给为的分析Q因个很单,我们直接来分析算法:首先我们考虑最理想的情? 1.数组的大是2的幂Q这样分下去始终可以?整除。假设ؓ2的kơ方Q即k=log2(n)? 2.每次我们选择的值刚好是中间|q样Q数l才可以被等分? W一层递归Q@环nơ,W二层@?*(n/2)...... 所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n 所以算法复杂度为O(log2(n)*n) 其他的情况只会比q种情况差,最差的情况是每ơ选择到的middle都是最值或最大|那么他将变成交换法(׃使用了递归Q情冉|p)。但是你认ؓq种情况发生的几率有多大Q?呵呵Q你完全不必担心q个问题。实践证明,大多数的情况Q快速排序L最好的? 如果你担心这个问题,你可以用堆排序Q这是一U稳定的O(log2(n)*n)法Q但是通常情况下速度要慢 于快速排序(因ؓ要重l堆Q? 三、其他排? 1.双向冒Q? 通常的冒泡是单向的,而这里是双向的,也就是说q要q行反向的工作? 代码看v来复杂,仔细理一下就明白了,是一个来回震荡的方式? 写这D代码的作者认样可以在冒的基上减一些交换(我不q么认ؓQ也许我错了Q? 反正我认是一D|的代码Q值得一看? #include <iostream.h> void Bubble2Sort(int* pData,int Count) { int iTemp; int left = 1; int right =Count -1; int t; do { //正向的部? for(int i=right;i>=left;i--) { if(pData[i]<pData[i-1]) { iTemp = pData[i]; pData[i] = pData[i-1]; pData[i-1] = iTemp; t = i; } } left = t+1; //反向的部? for(i=left;i<right+1;i++) { if(pData[i]<pData[i-1]) { iTemp = pData[i]; pData[i] = pData[i-1]; pData[i-1] = iTemp; t = i; } } right = t-1; }while(left<=right); } void main() { int data[] = {10,9,8,7,6,5,4}; Bubble2Sort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 2.SHELL排序 q个排序非常复杂Q看了程序就知道了? 首先需要一个递减的步长,q里我们使用的是9???Q最后的步长必须?Q? 工作原理是首先对盔R9-1个元素的所有内Ҏ序,然后再用同LҎ对相?-1个元素的排序以次cL? #include <iostream.h> void ShellSort(int* pData,int Count) { int step[4]; step[0] = 9; step[1] = 5; step[2] = 3; step[3] = 1; int iTemp; int k,s,w; for(int i=0;i<4;i++) { k = step[i]; s = -k; for(int j=k;j<Count;j++) { iTemp = pData[j]; w = j-k;//求上step个元素的下标 if(s ==0) { s = -k; s++; pData[s] = iTemp; } while((iTemp<pData[w]) && (w>=0) && (w<=Count)) { pData[w+k] = pData[w]; w = w-k; } pData[w+k] = iTemp; } } } void main() { int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1}; ShellSort(data,12); for (int i=0;i<12;i++) cout<<data[i]<<" "; cout<<"\n"; } 呵呵Q程序看h有些头疼。不q也不是很难Q把s==0的块Lp村֤了,q里是避免?步长造成E序异常而写的代码。这个代码我认ؓ很值得一看? q个法的得名是因ؓ其发明者的名字D.L.SHELL。依照参考资料上的说法:“׃复杂的数学原因避免?的幂ơ步长,它能降低法效率?#8221;另外法的复杂度为n?.2ơ幂。同样因为非常复杂ƈ“出本书讨论范围”的原因(我也不知道过E)Q我们只有结果了? 最后,希望大家愉快的编E。有什么意见,l我提吧Q? ]]> "没有扑ֈMFC80D.DLL"问题的解x?? http://www.shnenglu.com/softko/archive/2011/05/17/146539.htmleircQ eircQ Tue, 17 May 2011 01:31:00 GMT http://www.shnenglu.com/softko/archive/2011/05/17/146539.html http://www.shnenglu.com/softko/comments/146539.html http://www.shnenglu.com/softko/archive/2011/05/17/146539.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/146539.html http://www.shnenglu.com/softko/services/trackbacks/146539.html 用VS2005调试一个程序,出现“没有扑ֈMFC80D.DLL……”的提CZɽE序不能q行Q删掉Debug文g多w新编译问题依旧,上网查了一下,有说是vs路径的原因,有说是vs没装好的原因?/font>
?#8220;启动调试F5”的工具图标右侧有一?#8220;解决Ҏ配置”Q无意中其中的“Debug”改ؓ“Release”QF5通过Q运行正常,目目录下生?#8220;Release”文g夹,Debug方式生成?#8220;Debug"文gҎ无用的。原因如下:
DEBUG和RELEASE 版本差异及调试相关问题: I. 内存分配问题
1. 变量未初始化。下面的E序在debug中运行的很好?/font>
thing * search(thing * something) BOOL found; for(int i = 0; i < whatever.GetSize(); i++) { if(whatever[i]->field == something->field) { /* found it */ found = TRUE; break; } /* found it */ } if(found) return whatever[i]; else return NULL; 而在release中却不行Q因为debug中会自动l变量初始化found=FALSE,而在release版中则不会。所以尽可能的给变量、类或结构初始化?/font>
2. 数据溢出的问?nbsp; 如:char buffer[10]; int counter; lstrcpy(buffer, "abcdefghik");
在debug版中buffer的NULL覆盖了counter的高位,但是除非counter>16M,什么问题也没有。但是在release版中Qcounter可能被放在寄存器中,q样NULLp盖了buffer下面的空_可能是函数的返回地址Q这导致ACCESS ERROR?br /> 3. DEBUG版和RELEASE版的内存分配方式是不同的。如果你在DEBUG版中甌 ele ?6*sizeof(DWORD)=24bytes,实际上分配给你的?2bytesQdebug版以32bytes为单位分配)Q而在release版,分配l你的就?4bytesQrelease版以8bytes为单位)Q所以在debug版中如果你写ele[6],可能不会有什么问题,而在release版中Q就有ACCESS VIOLATE?/font>
II. ASSERT和VERIFY
1. ASSERT在Release版本中是不会被编译的?/font>
ASSERT宏是q样定义?/font>
#ifdef _DEBUG #define ASSERT(x) if( (x) == 0) report_assert_failure() #else #define ASSERT(x) #endif 实际上复杂一些,但无关紧要。假如你在这些语句中加了E序中必要有的代码 比如
ASSERT(pNewObj = new CMyClass);
pNewObj->MyFunction();
q种时候Release版本中的pNewObj不会分配到空?/font>
所以执行到下一个语句的时候程序会报该E序执行了非法操作的错误。这时可以用VERIFY Q?/font>
#ifdef _DEBUG #define VERIFY(x) if( (x) == 0) report_assert_failure() #else
#define VERIFY(x) (x) #endif q样的话Q代码在release版中可以执行了?/font>
III. 参数问题Q?/font>
自定义消息的处理函数Q必d义如下:
afx_msg LRESULT OnMyMessage(WPARAM, LPARAM);
q回值必LHRESULT型,否则Debug会过Q而Release出错
IV. 内存分配
保证数据创徏和清除的l一性:如果一个DLL提供一个能够创建数据的函数Q那么这个DLL同时应该提供一个函数销毁这些数据。数据的创徏和清除应该在同一个层ơ上?/font>
V. DLL的灾?/font>
Z不同版本DLL混合造成的不一致性Ş象的UCؓ “动态连接库的地?#8220;(DLL Hell) Q甚臛_软自׃q么?http://msdn.microsoft.com/library/techart/dlldanger1.htm)?/font>
如果你的E序使用你自qDLL时请注意Q?/font>
1. 不能debug和release版的DLL混合在一起用。debug都是debug版,release版都是release版?/font>
解决办法是将debug和release的程序分别放在主E序的debug和release目录?/font>
2. 千万不要以ؓ静态连接库会解决问题,那只会情况更糟p?/font>
VI. RELEASE板中的调试:
1. ASSERT() 改ؓ VERIFY() 。找出定义在"#ifdef _DEBUG"中的代码Q如果在RELEASE版本中需要这些代码请他们移到定义外。查找TRACE(...)中代码,因ؓq些代码在RELEASE中也不被~译。请认真查那些在RELEASE中需要的代码是否q没有被便宜?/p>
2. 变量的初始化所带来的不同,在不同的pȝQ或是在DEBUG/RELEASE版本间都存在q样的差异,所以请对变量进行初始化?/p>
3. 是否在编译时已经有了警告?请将警告U别讄??,然后保证在编译时没有警告出现.
VII. Project Settings" ?"C++/C " 目下优化选项改ؓDisbaleQDebugQ。编译器的优化可能导致许多意想不到的错误Q请参考http://www.pgh.net/~newcomer/debug_release.htm
1. 此外对RELEASE版本的Y件也可以q行调试Q请做如下改动:
?Project Settings" ?"C++/C " 目下设|?"category" ?"General" q且?Debug Info"讄?"Program Database"?/p>
?"Link"目下选中"Generate Debug Info"查框?/p>
"Rebuild All"
如此做法会生的一些限Ӟ
无法获得在MFC DLL中的变量的倹{?/p>
必须对该软g所使用的所有DLL工程都进行改动?/p>
另:
MS BUGQMS的一份技术文档中表明Q在VC5中对于DLL?Maximize Speed"优化选项q未被完全支持,因此q将会引起内存错误ƈDE序崩溃?/p>
2. www.sysinternals.com有一个程序DebugViewQ用来捕捉OutputDebugString的输出,q行h后(估计是自设ؓsystem debuggerQ就可以观看所有程序的OutputDebugString的输出。此后,你可以脱VC来运行你的程序ƈ观看调试信息?/p>
3. 有一个叫Gimpel Lint的静态代码检查工P据说比较好用。http://www.gimpel.com 不过要化$的?/p>
参考文献:
1) http://www.cygnus-software.com/papers/release_debugging.html
2) http://www.pgh.net/~newcomer/debug_release.htm
]]> Hash 法及其应用(? http://www.shnenglu.com/softko/archive/2010/12/02/135309.htmleircQ eircQ Thu, 02 Dec 2010 15:08:00 GMT http://www.shnenglu.com/softko/archive/2010/12/02/135309.html http://www.shnenglu.com/softko/comments/135309.html http://www.shnenglu.com/softko/archive/2010/12/02/135309.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/135309.html http://www.shnenglu.com/softko/services/trackbacks/135309.html 期:2004-07-30] 来源Q?a target="_blank" style="color: rgb(65, 81, 154); text-decoration: none; ">CSDN 作者: [字体Q?a style="color: rgb(65, 81, 154); text-decoration: none; ">?/a> ?/a> ?/a>] --------------- 什么是 Hash Hash 的重要特?nbsp; Hash 函数的实?nbsp; 主要?Hash 法 Hash 法的安全问?nbsp; Hash 法的应?nbsp; l??nbsp; ---------------
HashQ一般翻译做“散列”Q也有直接音译ؓ"哈希"的,是把Q意长度的输入Q又叫做预映, pre-imageQ,通过散列法Q变换成固定长度的输出,该输出就是散列倹{这U{换是一U压~映,也就是,散列值的I间通常q小于输入的I间Q不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入倹{?/p>
数学表述为:h = H(M) Q其中H( )--单向散列函数QM--L长度明文Qh--固定长度散列倹{?/p>
在信息安全领域中应用的Hash法Q还需要满_他关键特性:
W一当然是单向?one-way)Q从预映,能够单迅速的得到散列|而在计算上不可能构造一个预映射Q其散列结果等于某个特定的散列|x造相应的M=H-1(h)不可行。这P散列值就能在l计上唯一的表征输入|因此Q密码学上的 Hash 又被UCؓ"消息摘要(message digest)"Q就是要求能方便的将"消息"q行"摘要"Q但?摘要"中无法得到比"摘要"本n更多的关?消息"的信息?/p>
W二是抗冲突?collision-resistant)Q即在统计上无法产生2个散列值相同的预映。给定MQ计上无法扑ֈM'Q满H(M)=H(M') Q此谓弱抗冲H性;计算上也难以L一对Q意的M和M'Q满H(M)=H(M') Q此谓强抗冲H性。要?强抗冲突?主要是ؓ了防范所?生日d(birthday attack)"Q在一?0人的团体中,你能扑ֈ和你生日相同的h的概率是2.4%Q而在同一团体中,?人生日相同的概率?1.7%。类似的Q当预映的I间很大的情况下Q算法必L_的强度来保证不能L扑ֈ"相同生日"的h?/p>
W三是映分布均匀性和差分分布均匀性,散列l果中,?0 ?bit 和ؓ 1 ?bit Q其L应该大致相等Q输入中一?bit 的变化,散列l果中将有一半以上的 bit 改变Q这又叫?雪崩效应(avalanche effect)"Q要实现使散列结果中出现 1bit 的变化,则输入中臛_有一半以上的 bit 必须发生变化。其实质是必M输入中每一?bit 的信息,量均匀的反映到输出的每一?bit 上去Q输Z的每一?bitQ都是输入中可能多 bit 的信息一起作用的l果?/p>
Damgard ?Merkle 定义了所?#8220;压羃函数(compression function)”Q就是将一个固定长度输入,变换成较短的固定长度的输出,q对密码学实践上 Hash 函数的设计生了很大的媄响。Hash函数是被设计ؓZ通过特定压羃函数的不断重?#8220;压羃”输入的分l和前一ơ压~处理的l果的过E,直到整个消息都被压羃完毕Q最后的输出作ؓ整个消息的散列倹{尽还~Z严格的证明,但绝大多C界的研究者都同意Q如果压~函数是安全的,那么以上qŞ式散列Q意长度的消息也将是安全的。这是所?Damgard/Merkle l构Q?/p>
在下图中QQ意长度的消息被分拆成W合压羃函数输入要求的分l,最后一个分l可能需要在末尾M特定的填充字节,q些分组被序处理Q除了第一个消息分l将与散列初始化g起作为压~函数的输入外,当前分组和前一个分l的压羃函数输出一赯作ؓq一ơ压~的输入Q而其输出又将被作Z一个分l压~函数输入的一部分Q直到最后一个压~函数的输出Q将被作为整个消息散列的l果?/p>
MD5 ?SHA1 可以说是目前应用最q泛的Hash法Q而它们都是以 MD4 为基设计的?/p>
1) MD4 MD4(RFC 1320)?MIT ?Ronald L. Rivest ?1990 q设计的QMD ?Message Digest 的羃写。它适用?2位字长的处理器上用高速Y件实?-它是Z 32 位操作数的位操作来实现的。它的安全性不像RSA那样Z数学假设Q尽?Den Boer、Bosselaers ?Dobbertin 很快q分析和差分成功的d了它3轮变换中?2 轮,证明了它q不像期望的那样安全Q但它的整个法q没有真正被破解q,Rivest 也很快进行了改进?/p>
下面是一些MD4散列l果的例子:
MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d MD4 ("message digest") = d9130a8164549fe818874806e1c7014b MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
2) MD5 MD5(RFC 1321)?Rivest ?991q对MD4的改q版本。它对输入仍?12位分l,其输出是4?2位字的联,?MD4 相同。它较MD4所做的改进是:
1) 加入了第四轮 2) 每一步都有唯一的加法常敎ͼ 3) W二轮中的G函数?(X ?Y) ?(X ?Z) ?(Y ?Z)) 变ؓ ((X ?Z) ?(Y ?~Z))以减其对称性; 4) 每一步都加入了前一步的l果Q以加快"雪崩效应"Q?nbsp; 5) 改变了第2轮和W?轮中讉K输入子分l的序Q减了形式的相似程度; 6) q似优化了每轮的循环左移位移量,以期加快"雪崩效应"Q各轮的循环左移都不同?nbsp; 管MD5比MD4来得复杂Qƈ且速度较之要慢一点,但更安全Q在抗分析和抗差分方面表现更好?/p>
消息首先被拆成若q个512位的分组Q其中最?12位一个分l是“消息?填充字节(100…0)+64 位消息长?#8221;Q以保对于不同长度的消息,该分l不相同?4位消息长度的限制D了MD5安全的输入长度必d?64bitQ因为大?4位的长度信息被忽略。??2位寄存器字初始化为A=0x01234567QB=0x89abcdefQC=0xfedcba98QD=0x76543210Q它们将始终参与q算qŞ成最l的散列l果?/p>
接着各个512位消息分l以16?2位字的Ş式进入算法的d@环,512位消息分l的个数据决定了循环的次数。主循环?轮,每轮分别用到了非U性函?/p>
F(X, Y, Z) = (X ?Y) ?(~X ?Z) G(X, Y, Z) = (X ?Z) ?(Y ?~Z) H(X, Y, Z) =X ⊕ Y ⊕ Z I(X, Y, Z) = X ⊕ (Y ?~Z) q?轮变换是对进入主循环?12位消息分l的16?2位字分别q行如下操作Q将A、B、C、D的副本a、b、c、d中的3个经F、G、H、Iq算后的l果与第4个相加,再加?2位字和一?2位字的加法常敎ͼq将所得之值@环左U若q位Q最后将所得结果加上a、b、c、d之一Qƈ回送至ABCDQ由此完成一ơ@环?/p>
所用的加法常数p样一张表T[i]来定义,其中i?…64QT[i]是i的正弦绝对g4294967296ơ方的整数部分,q样做是Z通过正u函数和幂函数来进一步消除变换中的线性性?/p>
当所?12位分l都q算完毕后,ABCD的联将被输ZؓMD5散列的结果。下面是一些MD5散列l果的例子:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a 参考相应RFC文档可以得到MD4、MD5法的详l描q和法的C源代码?/p>
3) SHA1 及其?nbsp; SHA1是由NIST NSA设计为同DSA一起用的Q访问http://www.itl.nist.gov/fipspubs可以得到它的详细规范--[/url]"FIPS PUB 180-1 SECURE HASH STANDARD"。它寚w度小?64的输入,产生长度?60bit的散列|因此抗穷?brute-force)性更好。SHA-1 设计时基于和MD4相同原理,q且模仿了该法。因为它?60bit的散列|因此它有5个参与运的32位寄存器字,消息分组和填充方式与MD5相同Q主循环也同h4轮,但每轮进?0ơ操作,非线性运、移位和加法q算也与MD5cMQ但非线性函数、加法常数和循环左移操作的设计有一些区别,可以参考上面提到的规范来了解这些细节。下面是一些SHA1散列l果的例子:
SHA1 ("abc") = a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d SHA1 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 其他一些知名的Hash法q有MD2、N-Hash、RIPE-MD、HAVAL{等。上面提到的q些都属?U?Hash法。还有另2cHash法Q一cd是基于对U分l算法的单向散列法Q典型的例子是基于DES的所谓Davies-Meyer法Q另外还有经IDEA改进的Davies-Meyer法Q它们两者目前都被认为是安全的算法。另一cLZ模运?LҎ的,也就是基于公开密钥法的,但因为其q算开销太大Q而缺乏很好的应用前景?/p>
没有通过分析和差分攻击考验的算法,大多都已l夭折在实验室里了,因此Q如果目前流行的Hash法能完全符合密码学意义上的单向性和抗冲H性,׃证了只有IDQ才是破坏Hashq算安全Ҏ的唯一Ҏ。ؓ了对抗弱抗冲H性,我们可能要穷举个数和散列值空间长度一样大的输入,卛_?^128?^160个不同的输入Q目前一台高档个人电脑可能需?0^25q才能完成这一艰巨的工作,即是最高端的ƈ行系l,q也不是在几千年里的q得完的事。而因?生日d"有效的降低了需要穷丄I间Q将光低ؓ大约1.2*2^64?.2*2^80Q所以,强抗冲突性是军_Hash法安全性的关键?/p>
在NIST新的 Advanced Encryption Standard (AES)中,使用了长度ؓ128?92?56bit 的密钥,因此相应的设计了 SHA256、SHA384、SHA512Q它们将提供更好的安全性?/p>
Hash法在信息安全方面的应用主要体现在以下的3个方面:
1) 文g校验 我们比较熟悉的校验算法有奇偶校验和CRC校验Q这2U校验ƈ没有抗数据篡改的能力Q它们一定程度上能检ƈU正数据传输中的信道误码Q但却不能防止对数据的恶意破坏?/p>
MD5 Hash法?数字指纹"Ҏ,使它成ؓ目前应用最q泛的一U文件完整性校验和(Checksum)法Q不Unixpȝ有提供计md5 checksum的命令。它常被用在下面?U情况下Q?/p>
W一是文件传送后的校验,得到的目标文g计算 md5 checksumQ与源文件的md5 checksum 比对Q由两?md5 checksum 的一致性,可以从统计上保证2个文件的每一个码元也是完全相同的。这可以验文件传输过E中是否出现错误Q更重要的是可以保证文g在传输过E中未被恶意改。一个很典型的应用是ftp服务Q用户可以用来保证多ơ断点箋传,特别是从镜像站点下蝲的文件的正确性?/p>
更出色的解决Ҏ是所谓的代码{Q文件的提供者在提供文g的同Ӟ提供Ҏ件Hash值用自己的代码签名密钥进行数字签名的|及自q代码{证书。文件的接受者不仅能验证文g的完整性,q可以依据自己对证书{֏者和证书拥有者的信QE度Q决定是否接受该文g。浏览器在下载运行插件和java程序时Q用的是q样的模式?/p>
W二是用作保存二q制文gpȝ的数字指U,以便文件系l是否未l允许的被修攏V不系l管?pȝ安全软g都提供这一文gpȝ完整性评估的功能Q在pȝ初始安装完毕后,建立Ҏ件系l的基础校验和数据库Q因为散列校验和的长度很,它们可以方便的被存放在容量很的存储介质上。此后,可以定期或根据需要,再次计算文gpȝ的校验和Q一旦发C原来保存的值有不匹配,说明该文件已l被非法修改Q或者是被病毒感染,或者被木马E序替代。TripWire提供了一个此cd用的典型例子?/p>
更完的Ҏ是?MAC"?MAC" 是一个与Hash密切相关的名词,即信息鉴权码(Message Authority Code)。它是与密钥相关的Hash|必须拥有该密钥才能检验该Hash倹{文件系l的数字指纹也许会被保存在不可信ȝ介质上,只对拥有该密钥者提供可鉴别性。ƈ且在文g的数字指UҎ可能需要被修改的情况下Q只有密钥的拥有者可以计出新的散列|而企囄坏文件完整性者却不能得逞?/p>
2) 数字{ Hash 法也是C密码体系中的一个重要组成部分。由于非对称法的运速度较慢Q所以在数字{协议中,单向散列函数扮演了一个重要的角色?/p>
在这U签名协议中Q双方必M先协商好双方都支持的Hash函数和签名算法?/p>
{方先对该数据文gq行计算其散列|然后再对很短的散列值结?-如Md5?6个字节,SHA1?0字节Q用非对U算法进行数字签名操作。对方在验证{Ӟ也是先对该数据文件进行计其散列|然后再用非对U算法验证数字签名?/p>
?Hash |又称"数字摘要"q行数字{Q在l计上可以认ZҎ件本w进行数字签名是{效的。而且q样的协议还有其他的优点Q?/p>
首先Q数据文件本w可以同它的散列值分开保存Q签名验证也可以q数据文g本n的存在而进行?/p>
再者,有些情况下签名密钥可能与解密密钥是同一个,也就是说Q如果对一个数据文件签名,与对其进行非对称的解密操作是相同的操作,q是相当危险的,恶意的破坏者可能将一个试N你将其解密的文gQ充当一个要求你{的文件发送给你。因此,在对M数据文gq行数字{Ӟ只有对其HashD行签名才是安全的?/p>
3) 鉴权协议 如下的鉴权协议又被称?挑战--认证模式Q在传输信道是可被侦听,但不可被改的情况下Q这是一U简单而安全的Ҏ?/p>
需要鉴权的一方,向将被鉴权的一方发送随ZQ?#8220;挑战”Q,被鉴权方该随机串和自己的鉴权口令字一赯?Hash q算后,q还鉴权方,鉴权方将收到的Hashg在己端用该随Z和对方的鉴权口o字进?Hash q算的结果相比较Q?#8220;认证”Q,如相同,则可在统计上认ؓҎ拥有该口令字Q即通过鉴权?/p>
POP3协议中就有这一应用的典型例子:
S: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us> C: APOP mrose c4c9334bac560ecc979e58001b3e22fb S: +OK maildrop has 1 message (369 octets) 在上面的一DPOP3协议会话中,双方都共享的对称密钥Q鉴权口令字Q是tanstaafQ服务器发出的挑战是<1896.697170952@dbc.mtview.ca.us>Q客LҎ战的应答是MD5("<1896.697170952@dbc.mtview.ca.us>tanstaaf") = c4c9334bac560ecc979e58001b3e22fbQ这个正的应答使其通过了认证?/p>
散列法长期以来一直在计算机科学中大量应用Q随着C密码学的发展Q单向散列函数已l成Z息安全领域中一个重要的l构模块Q我们有理由深入研究其设计理论和应用Ҏ?/p>
]]>C++随机数生成方法(转蝲) http://www.shnenglu.com/softko/archive/2010/12/02/135228.htmleircQ eircQ Thu, 02 Dec 2010 00:42:00 GMT http://www.shnenglu.com/softko/archive/2010/12/02/135228.html http://www.shnenglu.com/softko/comments/135228.html http://www.shnenglu.com/softko/archive/2010/12/02/135228.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/135228.html http://www.shnenglu.com/softko/services/trackbacks/135228.html
原文 http://www.cnblogs.com/finallyliuyu/archive/2010/10/11/1848130.html
一、C++中不能用random()函数
==================================================================================
本文由青村֎创ƈ依GPL-V2及其后箋版本发放Q{载请注明出处且应包含本行声明?/p>
C++中常用rand()函数生成随机敎ͼ但严格意义上来讲生成的只是伪随机敎ͼpseudo-random integral
numberQ。生成随机数旉要我们指定一个种子,如果在程序内循环Q那么下一ơ生成随机数时调用上一ơ的l果作ؓU子。但如果分两ơ执行程序,那么?
于种子相同,生成?#8220;随机?#8221;也是相同的?/p>
在工E应用时Q我们一般将pȝ当前旉(Unix旉)作ؓU子Q这L成的随机数更接近于实际意义上的随机数。给一下例E如下:
#include <iostream> #include <ctime> #include <cstdlib> using namespace std;
int main() { double random(double,double); srand(unsigned(time(0))); for(int icnt = 0; icnt != 10; ++icnt) cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl; return 0; }
double random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } /* q行l果 * No.1: 3 * No.2: 9 * No.3: 0 * No.4: 9 * No.5: 5 * No.6: 6 * No.7: 9 * No.8: 2 * No.9: 9 * No.10: 6 */ 利用q种Ҏ能不能得到完全意义上的随机数呢?g9有点多哦Q却没有1,4,7Q!我们来做一个概率实验,生成1000万个随机敎ͼ?-9q?0个数出现的频率是不是大致相同的。程序如下: #include <iostream> #include <ctime> #include <cstdlib> #include <iomanip> using namespace std;
int main() { double random(double,double); int a[10] = {0}; const int Gen_max = 10000000; srand(unsigned(time(0))); for(int icnt = 0; icnt != Gen_max; ++icnt) switch(int(random(0,10))) { case 0: a[0]++; break; case 1: a[1]++; break; case 2: a[2]++; break; case 3: a[3]++; break; case 4: a[4]++; break; case 5: a[5]++; break; case 6: a[6]++; break; case 7: a[7]++; break; case 8: a[8]++; break; case 9: a[9]++; break; default: cerr << "Error!" << endl; exit(-1); } for(int icnt = 0; icnt != 10; ++icnt)
cout << icnt << ": " << setw(6) <<
setiosflags(ios::fixed) << setprecision(2) <<
double(a[icnt])/Gen_max*100 << "%" << endl; return 0; }
double random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } /* q行l果 * 0: 10.01% * 1: 9.99% * 2: 9.99% * 3: 9.99% * 4: 9.98% * 5: 10.01% * 6: 10.02% * 7: 10.01% * 8: 10.01% * 9: 9.99% */ 可知用这U方法得到的随机数是满l计规律的?/p>
另:在Linux下利用GCC~译E序Q即使我执行?000000ơ运,是否random函数定义了inline函数g对程序没有Q何媄响,有理q信,GCC已经为我们做了优化。但是冥冥之中我又记得要做inline优化得加O3才行...
不行Q于是我们把循环ơ数改ؓ10亿次Q用time命o查看执行旉Q?br>chinsung@gentoo ~/workspace/test/Debug $ time ./test 0: 10.00% 1: 10.00% 2: 10.00% 3: 10.00% 4: 10.00% 5: 10.00% 6: 10.00% 7: 10.00% 8: 10.00% 9: 10.00%
real 2m7.768s user 2m4.405s sys 0m0.038schinsung@gentoo ~/workspace/test/Debug $ time ./test 0: 10.00% 1: 10.00% 2: 10.00% 3: 10.00% 4: 10.00% 5: 10.00% 6: 10.00% 7: 10.00% 8: 10.00% 9: 10.00%
real 2m7.269s user 2m4.077s sys 0m0.025s
前一ơؓq行inline优化的情形,后一ơؓ没有作inline优化的情形,两次l果相差不大Q甚臛_Ҏ标后者还要好一些,不知是何~由...
=================================================================================
random函数不是ANSI C标准Q不能在gcc,vc{编译器下编译通过?
可改用C++下的rand函数来实现?nbsp; 1、C++标准函数库提供一随机数生成器randQ返?QRAND_MAX之间均匀分布的伪随机整数?
RAND_MAX必须臛_?2767。rand()函数不接受参敎ͼ默认?为种子(卌v始|?
随机数生成器L以相同的U子开始,所以Ş成的伪随机数列也相同Q失M随机意义。(但这样便于程序调试) 2、C++中另一函数srandQ)Q可以指定不同的敎ͼ无符h数变元)为种子。但是如果种子相同,伪随机数列也相同。一个办法是让用戯入种子,但是仍然不理惟? 3?比较理想的是用变化的敎ͼ比如旉来作为随机数生成器的U子?time的值每时每刻都不同。所以种子不同,所以,产生的随机数也不同? // C++随机函数QVC programQ? #include <stdio.h> #include <iostream> #include <time.h> using namespace std; #define MAX 100 int main(int argc, char* argv[]) { srand( (unsigned)time( NULL ) );//srand()函数产生一个以当前旉开始的随机U子.应该攑֜for{@环语句前?不然要很长时间等? for (int i=0;i<10;i++) cout<<rand()%MAX<<endl;//MAX为最大|光机域?~MAX-1 return 0; } 二、rand()的用? rand()不需要参敎ͼ它会q回一个从0到最大随机数的Q意整敎ͼ最大随机数的大通常是固定的一个大整数?q样Q如果你要?~10?0个整敎ͼ可以表达为: int N = rand() % 11; q样QN的值就是一?~10的随机数Q如果要产生1~10Q则是这P int N = 1 + rand() % 10; ȝ来说Q可以表CZؓQ? a + rand() % n
其中的a是v始|n是整数的范围? a + rand() % (b-a+1)
pC a~b之间的一个随机数若要0~1的小敎ͼ则可以先取得0~10的整敎ͼ然后均除?0卛_得到随机到十分位?0个随机小敎ͼ若要得到随机到百
分位的随机小敎ͼ则需要先得到0~100?0个整敎ͼ然后均除?00Q其它情况依此类推? 通常rand()产生的随机数在每ơ运行的时候都是与上一ơ相同的Q这是有意这栯计的Q是Z便于E序的调试。若要生每ơ不同的随机敎ͼ可以使用srand( seed )函数q行随机化,随着seed的不同,p够生不同的随机数? 如大家所_q可以包含time.h头文Ӟ然后使用srand(time(0))来用当前时间随机数发生器随机化,q样可以保证每两次q行时可以得C同的随机数序?只要两次q行的间隔超q?U??/p>
]]> trie?-详解 http://www.shnenglu.com/softko/archive/2010/11/26/134701.htmleircQ eircQ Fri, 26 Nov 2010 01:48:00 GMT http://www.shnenglu.com/softko/archive/2010/11/26/134701.html http://www.shnenglu.com/softko/comments/134701.html http://www.shnenglu.com/softko/archive/2010/11/26/134701.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/134701.html http://www.shnenglu.com/softko/services/trackbacks/134701.html 文章作者: yx_th000 文章来源Q?/span>C herish_yimi ( http://www.cnblogs.com/cherish_yimi/ ) 转蝲h明,谢谢合作?br> 关键词:trie trie?数据l构
前几天学习了q查集和trie树,q里ȝ一下trie?br> 本文讨论一|单的trie树,Z英文26个字母组成的字符Ԍ讨论插入字符丌Ӏ判断前~是否存在、查扑֭W串{基本操作;至于trie树的删除单个节点实在是少见,故在此不做详解?/span>
l Trie 原理
Trie 的核心思想是空间换旉。利用字W串的公共前~来降低查询时间的开销以达到提高效率的目的?/span>
l Trie 性质
好多trie的根节点不包含Q何字W信息,我所习惯的trie根节点却是包含信息的Q而且认ؓq样也方便,下面说一下它的性质 (Z本文所讨论的简单trie?
1. 字符的种数决定每个节点的出度Q即branch数组(I间换时间思想)
2. branch 数组的下标代表字W相对于a的相对位|?/span>
3. 采用标记的方法确定是否ؓ字符丌Ӏ?/span>
4. 插入、查扄复杂度均为O(len),len为字W串长度
l Trie 的示意图
如图所C,该trie树存有abc、d、da、dda四个字符Ԍ如果是字W串会在节点的尾部进行标记。没有后l字W的branch分支指向NULL l Trie Trie 的优点D?/span>
已知n个由写字母构成的^均长度ؓ10的单?判断其中是否存在某个串ؓ另一个串的前~子串。下面对?U方法:
1. 最Ҏ惛_的:即从字符串集中从头往后搜Q看每个字符串是否ؓ字符串集中某个字W串的前~Q复杂度为O(n^2)?/span>
2. 使用hashQ我们用hash存下所有字W串的所有的前缀子串。徏立存有子串hash的复杂度为O(n*len)。查询的复杂度ؓO(n)* O(1)= O(n)?/span>
3. ?
用trieQ因为当查询如字W串abc是否为某个字W串的前~Ӟ昄以b,c,d....{不是以a开头的字符串就不用查找了。所以徏立trie的复?
度ؓO(n*len)Q而徏?查询在trie中是可以同时执行的,建立的过E也可以成为查询的q程Qhash׃能实现这个功能。所以ȝ复杂度ؓ
O(n*len)Q实际查询的复杂度只是O(len)?br>
解释一?
hashZ么不能将建立与查询同时执行,例如有串Q?11Q?11456输入Q如果要同时执行建立与查询,q程是查询911Q没有,然后存入9?
91?11Q查?11456Q没有然后存?114?1145?11456Q而程序没有记忆功能,q不知道911在输入数据中出现q。所以用
hash必须先存入所有子Ԍ然后for循环查询?/span>
而trie树便?
以,存入911后,已经记录911为出现的字符Ԍ在存?11456的过E中p发现而输出答案;倒过来亦可以Q先存入911456Q在存入911Ӟ
当指针指向最后一?ӞE序会发现这?已经存在Q说?11必定是某个字W串的前~Q该思想是我在做pku上的3630中发现的Q详见本文配套的“?
门练?#8221;?/span>
l Trie 的简单实 ?插入、查 ?
Code 1 2 #include < iostream > 3 using namespace std; 4 5 const int branchNum = 26 ; // 声明帔R 6 int i; 7 8 struct Trie_node 9 { 10 bool isStr; // 记录此处是否构成一个串?/span>11 Trie_node * next[branchNum]; // 指向各个子树的指?下标0-25代表26字符 12 Trie_node():isStr( false ) 13 { 14 memset(next,NULL,sizeof (next)); 15 }16 } ; 17 18 class Trie 19 { 20 public : 21 Trie();22 void insert( const char * word); 23 bool search( char * word); 24 void deleteTrie(Trie_node * root); 25 private : 26 Trie_node* root; 27 }; 28 29 Trie::Trie()30 { 31 root = new Trie_node(); 32 }33 34 void Trie::insert( const char * word) 35 { 36 Trie_node * location = root; 37 while ( * word) 38 { 39 if (location -> next[ * word - ' a ' ] == NULL) // 不存在则建立 40 { 41 Trie_node * tmp = new Trie_node(); 42 location-> next[ * word - ' a ' ] = tmp; 43 } 44 location = location -> next[ * word - ' a ' ]; // 每插入一步,相当于有一个新串经q,指针要向下移?/span>45 word ++ ; 46 } 47 location-> isStr = true ; // 到达N,标记一个串 48 } 49 50 bool Trie::search( char * word) 51 { 52 Trie_node * location = root; 53 while ( * word && location) 54 { 55 location = location -> next[ * word - ' a ' ]; 56 word++ ; 57 }58 return (location != NULL && location -> isStr); 59 }60 61 void Trie::deleteTrie(Trie_node * root) 62 { 63 for (i = 0 ; i < branchNum; i ++ ) 64 { 65 if (root -> next[i] != NULL) 66 { 67 deleteTrie(root-> next[i]); 68 }69 }70 delete root;71 }72 73 void main() // 单测?/span>74 { 75 Trie t;76 t.insert(" a " ); 77 t.insert(" abandon " ); 78 char * c = " abandoned " ; 79 t.insert(c);80 t.insert(" abashed " ); 81 if (t.search( " abashed " )) 82 printf(" true\n " ); 83 }
]]>使用ADO的具体方?? http://www.shnenglu.com/softko/archive/2010/11/08/132988.htmleircQ eircQ Mon, 08 Nov 2010 05:49:00 GMT http://www.shnenglu.com/softko/archive/2010/11/08/132988.html http://www.shnenglu.com/softko/comments/132988.html http://www.shnenglu.com/softko/archive/2010/11/08/132988.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/132988.html http://www.shnenglu.com/softko/services/trackbacks/132988.html 阅读全文 ]]> DataGridQ提C?can not initialize data binding"(? http://www.shnenglu.com/softko/archive/2010/10/11/129441.htmleircQ eircQ Mon, 11 Oct 2010 07:55:00 GMT http://www.shnenglu.com/softko/archive/2010/10/11/129441.html http://www.shnenglu.com/softko/comments/129441.html http://www.shnenglu.com/softko/archive/2010/10/11/129441.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/129441.html http://www.shnenglu.com/softko/services/trackbacks/129441.html
q两天遇C个问题,是q行可执行文件时Q出?can not initialize data binding"错误Q原因:
使用DATAGRID控gQ除了注册MSDATGRD.OCX?q需要注册一下MSSTDFMT.DLL才可以。MSSTDFMT.DLL是微?
标准数据格式对象相关动态链接库文gQ引用名UCؓ“Microsoft Data Formatting Object
Library”Q如果在开发程序中有数据绑定,是通过它对数据格式化后再绑定到控g的。如果用到数据绑定控Ӟ那么p记得?
MSSTDFMT.DLL加到安装E序里面?/p>
注:有的电脑注册MSDATGRD.OCX、MSSTDFMT.DLLQ所以未出现此类情况?/p>
解决ҎQ?/p>
Ҏ一Q?/p>
E序打包ӞMSDATGRD.OCX、MSSTDFMT.DLL都加载上厅R?/p>
Ҏ二:
开?〉运行:
regsvr32 MSDATGRD.OCX
regsvr32 MSSTDFMT.DLL
]]> C语言字节寚w详解(? http://www.shnenglu.com/softko/archive/2010/09/17/126825.htmleircQ eircQ Fri, 17 Sep 2010 01:49:00 GMT http://www.shnenglu.com/softko/archive/2010/09/17/126825.html http://www.shnenglu.com/softko/comments/126825.html http://www.shnenglu.com/softko/archive/2010/09/17/126825.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/126825.html http://www.shnenglu.com/softko/services/trackbacks/126825.html 一?
什么是寚wQ以及ؓ什么要寚wQ?/font> 1.
C计算Z内存I间都是按照byte划分的,从理Z讲似乎对Mcd的变量的讉K可以从Q何地址开始,但实际情冉|在访问特定变量的时候经常在特定?
内存地址讉KQ这需要各cd数据按照一定的规则在空间上排列Q而不是顺序的一个接一个的排放Q这是寚w?br> 2.
寚w的作用和原因Q各个硬件^台对存储I间的处理上有很大的不同。一些^台对某些特定cd的数据只能从某些特定地址开始存取。其他^台可能没有这U情况,
但是最常见的是如果不按照适合其^台的要求Ҏ据存放进行对齐,会在存取效率上带来损失。比如有些^台每ơ读都是从偶地址开始,如果一个int型(假设?
32位)如果存放在偶地址开始的地方Q那么一个读周期可以读出,而如果存攑֜奇地址开始的地方Q就可能会需?个读周期Qƈ对两ơ读出的l果的高?
字节q行拼凑才能得到该int数据。显然在d效率上下降很多。这也是I间和时间的博弈?font size="3"> 二、对齐的实现
通常Q我们写E序的时候,不需要考虑寚w问题。编译器会替我们选择适合目标q_的对齐策略。当Ӟ我们也可以通知l编译器传递预~译指o而改变对指定数据
的对齐方法?br>
但是Q正因ؓ我们一般不需要关心这个问题,所以因为编辑器Ҏ据存攑ց了对齐,而我们不了解的话Q常怼对一些问题感到迷惑。最常见的就是struct?
据结构的sizeofl果Q出乎意料。ؓ此,我们需要对寚w法所了解?br> 寚w的算法:
׃各个q_和编译器的不同,C本h使用的gcc version
3.2.2~译器(32位x86q_Qؓ例子Q来讨论~译器对struct数据l构中的各成员如何进行对齐的?br> 讄构体如下定义Q?br>
struct A { int a; char b; short c; };
l构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个。所以A用到的空间应该是7字节。但是因为编译器
要对数据成员在空间上q行寚w?br> 所以用sizeof(strcut A)gؓ8?br> 现在把该l构体调整成员变量的序?br>
struct B { char b; int a; short c; };
q时候同hd7个字节的变量Q但是sizeof(struct B)的值却?2?br> 下面我们使用预编译指?pragma pack
(value)来告诉编译器Q用我们指定的寚w值来取代~省的?br> #pragma pack (2) /*指定?字节寚w*/
struct C { char b; int a; short c; };
#pragma pack () /*取消指定寚wQ恢复缺省对?/ sizeof(struct C)值是8?br>
修改寚wgؓ1Q?br> #pragma pack (1) /*指定?字节寚w*/ struct D { char
b; int a; short c; }; #pragma pack ()
/*取消指定寚wQ恢复缺省对?/ sizeof(struct D)gؓ7?br>
对于char型数据,其自w对齐gؓ1Q对于short型ؓ2Q对于int,float,doublecdQ其自n寚wgؓ4Q单位字节?br>
q里面有四个概念| 1)数据cd自n的对齐|是上面交代的基本数据类型的自n寚w倹{?br> 2)指定寚w|#pragma
pack (value)时的指定寚w值value?br> 3)l构体或者类的自w对齐|其成员中自n寚w值最大的那个倹{?br>
4)数据成员、结构体和类的有效对齐|自n寚w值和指定寚wg较小的那个倹{?br>
有了q些|我们可以很方便的来讨论具体数据l构的成员和其自w的寚w方式。有效对齐值N是最l用来决定数据存攑֜址方式的|最重要。有效对齐NQ就
是表C?#8220;寚w在N?#8221;Q也是说该数据?存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址是
数据l构的v始地址。结构体的成员变量要寚w排放Q结构体本n也要Ҏ自n的有效对齐值圆?是l构体成员变量占用总长度需要是对结构体有效寚w值的?
数倍,l合下面例子理解)。这样就不难理解上面的几个例子的g?br> 例子分析Q?br> 分析例子BQ?br> struct B {
char b; int a; short c; };
假设B从地址I间0x0000开始排放。该例子中没有定义指定对齐|在笔者环境下Q该值默认ؓ4。第一个成员变量b的自w对齐值是1Q比指定或者默认指
定对齐?,所以其有效寚wgؓ1Q所以其存放地址0x0000W合0x0000%1=0.W二个成员变量aQ其自n寚wgؓ4Q所以有效对齐g?
4Q所以只能存攑֜起始地址?x0004?x0007q四个连l的字节I间中,复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自n寚w
gؓ2Q所以有效对齐g?Q可以存攑֜0x0008?x0009q两个字节空间中Q符?x0008%2=0。所以从0x0000?x0009?
攄都是B内容。再看数据结构B的自w对齐gؓ其变量中最大对齐?q里是bQ所以就?Q所以结构体的有效对齐g?。根据结构体圆整的要求,
0x0009?x0000=10字节Q(10Q?Q%4Q?。所?x0000A?x000B也ؓl构体B所占用。故B?x0000?x000B
共有12个字?sizeof(struct B)=12; 同理,分析上面例子CQ?br> #pragma pack (2)
/*指定?字节寚w*/ struct C { char b; int a; short
c; }; #pragma pack () /*取消指定寚wQ恢复缺省对?/
W一个变量b的自w对齐gؓ1Q指定对齐gؓ2Q所以,其有效对齐gؓ1Q假设C?x0000开始,那么b存放?x0000Q符?x0000%1=
0;W二个变量,自n寚wgؓ4Q指定对齐gؓ2Q所以有效对齐gؓ2Q所以顺序存攑֜0x0002?x0003?x0004?x0005四个q箋
字节中,W合0x0002%2=0。第三个变量c的自w对齐gؓ2Q所以有效对齐gؓ2Q顺序存?br>
?x0006?x0007中,W合0x0006%2=0。所以从0x0000?x00007共八字节存放的是C的变量。又C的自w对齐gؓ4Q所?
C的有效对齐gؓ2。又8%2=0,C只占?x0000?x0007的八个字节。所以sizeof(struct C)=8. ?
了以上的解释Q相信你对C语言的字节对齐概念应该有了清楚的认识了吧。在|络E序中,掌握q个概念可是很重要的喔,在不同^C_比如在Windows
和Linux之间Q传?q制(比如l构体)Q那么在q两个^台间必须要定义相同的寚w方式Q不然莫名其妙的Z一些错Q可是很难排查的哦^_^?/font> ]]>
þһۺ |
þþþAVרվ |
þۺɫHEZYO |
þۺϾƷþ |
þۺϾþ߾Ʒ |
ѾþҹƷ |
Ʒ91þþþþþ |
ƷþþþþþþþĻ |
պƷרþþ |
þˬˬƬAV |
Ʒ99þþƷ |
þҹҹݺ |
Ʒһþ |
ձƷþþþþþþ |
þer99ȾƷһ |
2021þþƷѹۿ |
ݺݾƷþþĻ |
ƷþþĻ |
99þ˾ƷۺϹۿ |
һƷƷþ
|
2021ƷþþƷ |
þþƷֻоƷ66 |
ŷۺϾþ |
þþƷһ |
þ96Ʒþþ |
þۺ88 |
Ʒþþò |
þþƷһ |
Ƶþ |
Ʒһþ㽶߿ |
þù鶹91 |
9þ9þþƷ |
ŮþþƷ㽶69 |
aaaƷþþùƬ |
ƷþSM
|
뾫Ʒþһ |
þƵ1 |
պavþþƷ |
Ʒһþ |
ھƷ˾þþþ777 |
þAAAƬ69 |