??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV无码久久精品狠狠爱浪潮,久久久久久夜精品精品免费啦,亚洲伊人久久综合影院http://www.shnenglu.com/softko/淡薄名利,修nL?/description>zh-cnWed, 07 May 2025 13:40:37 GMTWed, 07 May 2025 13:40:37 GMT60数组与指针的区别 http://www.shnenglu.com/softko/archive/2013/02/19/197934.htmleircQeircQTue, 19 Feb 2013 05:33:00 GMThttp://www.shnenglu.com/softko/archive/2013/02/19/197934.htmlhttp://www.shnenglu.com/softko/comments/197934.htmlhttp://www.shnenglu.com/softko/archive/2013/02/19/197934.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/197934.htmlhttp://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>

a

0xffaa

p

0xffcc

? 一个简单的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>

eircQ 2013-02-19 13:33 发表评论
]]>
新的一q_新的一天,新的气象。2Q1Q,我来也?/title><link>http://www.shnenglu.com/softko/archive/2012/01/20/164390.html</link><dc:creator>eircQ</dc:creator><author>eircQ</author><pubDate>Thu, 19 Jan 2012 17:38:00 GMT</pubDate><guid>http://www.shnenglu.com/softko/archive/2012/01/20/164390.html</guid><wfw:comment>http://www.shnenglu.com/softko/comments/164390.html</wfw:comment><comments>http://www.shnenglu.com/softko/archive/2012/01/20/164390.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/softko/comments/commentRss/164390.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/softko/services/trackbacks/164390.html</trackback:ping><description><![CDATA[<br />      可以?012是{折的一q?br /><br />      我也开始思考自己?br />      公司在{型,我也在{变?br />      <br />      2012q的目标Q?br />      一.控制自己?br />  做自己对自己持箋受益的事情?br />  <br />  ?不断地学习。学习前人的l验Q避免前人的错误?br />      看书Q学习技能,学习历史Q,观察周围的hQ思考?br /><br />      ?认识自己。努力去做好自己。徏设自q原则。(每天思考)<br />      <br />      ?更加Ȁ情地ȝqz,去融入到生活Q工作中。真诚对待每一个h?br /><br /><br /><br /><img src ="http://www.shnenglu.com/softko/aggbug/164390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/softko/" target="_blank">eircQ</a> 2012-01-20 01:38 <a href="http://www.shnenglu.com/softko/archive/2012/01/20/164390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>各种排序法介绍http://www.shnenglu.com/softko/archive/2011/06/17/148828.htmleircQeircQFri, 17 Jun 2011 00:09:00 GMThttp://www.shnenglu.com/softko/archive/2011/06/17/148828.htmlhttp://www.shnenglu.com/softko/comments/148828.htmlhttp://www.shnenglu.com/softko/archive/2011/06/17/148828.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/148828.htmlhttp://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?

eircQ 2011-06-17 08:09 发表评论
]]>
"没有扑ֈMFC80D.DLL"问题的解x??http://www.shnenglu.com/softko/archive/2011/05/17/146539.htmleircQeircQTue, 17 May 2011 01:31:00 GMThttp://www.shnenglu.com/softko/archive/2011/05/17/146539.htmlhttp://www.shnenglu.com/softko/comments/146539.htmlhttp://www.shnenglu.com/softko/archive/2011/05/17/146539.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/146539.htmlhttp://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



eircQ 2011-05-17 09:31 发表评论
]]>
Hash 法及其应用(?http://www.shnenglu.com/softko/archive/2010/12/02/135309.htmleircQeircQThu, 02 Dec 2010 15:08:00 GMThttp://www.shnenglu.com/softko/archive/2010/12/02/135309.htmlhttp://www.shnenglu.com/softko/comments/135309.htmlhttp://www.shnenglu.com/softko/archive/2010/12/02/135309.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/135309.htmlhttp://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>



eircQ 2010-12-02 23:08 发表评论
]]>
C++随机数生成方法(转蝲)http://www.shnenglu.com/softko/archive/2010/12/02/135228.htmleircQeircQThu, 02 Dec 2010 00:42:00 GMThttp://www.shnenglu.com/softko/archive/2010/12/02/135228.htmlhttp://www.shnenglu.com/softko/comments/135228.htmlhttp://www.shnenglu.com/softko/archive/2010/12/02/135228.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/135228.htmlhttp://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.038s
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.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>



eircQ 2010-12-02 08:42 发表评论
]]>
trie?-详解http://www.shnenglu.com/softko/archive/2010/11/26/134701.htmleircQeircQFri, 26 Nov 2010 01:48:00 GMThttp://www.shnenglu.com/softko/archive/2010/11/26/134701.htmlhttp://www.shnenglu.com/softko/comments/134701.htmlhttp://www.shnenglu.com/softko/archive/2010/11/26/134701.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/134701.htmlhttp://www.shnenglu.com/softko/services/trackbacks/134701.html文章作者:yx_th000 文章来源Q?/span>Cherish_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的简单实?插入、查?


 1
 2#include <iostream>
 3using namespace std;
 4
 5const int branchNum = 26//声明帔R 
 6int i;
 7
 8struct 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
18class Trie
19{
20public:
21    Trie();
22    void insert(const char* word);
23    bool search(char* word); 
24    void deleteTrie(Trie_node *root);
25private:
26    Trie_node* root;
27}
;
28
29Trie::Trie()
30{
31    root = new Trie_node();
32}

33
34void 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
50bool 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
61void 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
73void 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}



eircQ 2010-11-26 09:48 发表评论
]]>
使用ADO的具体方??http://www.shnenglu.com/softko/archive/2010/11/08/132988.htmleircQeircQMon, 08 Nov 2010 05:49:00 GMThttp://www.shnenglu.com/softko/archive/2010/11/08/132988.htmlhttp://www.shnenglu.com/softko/comments/132988.htmlhttp://www.shnenglu.com/softko/archive/2010/11/08/132988.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/132988.htmlhttp://www.shnenglu.com/softko/services/trackbacks/132988.html阅读全文

eircQ 2010-11-08 13:49 发表评论
]]>
DataGridQ提C?can not initialize data binding"(?http://www.shnenglu.com/softko/archive/2010/10/11/129441.htmleircQeircQMon, 11 Oct 2010 07:55:00 GMThttp://www.shnenglu.com/softko/archive/2010/10/11/129441.htmlhttp://www.shnenglu.com/softko/comments/129441.htmlhttp://www.shnenglu.com/softko/archive/2010/10/11/129441.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/129441.htmlhttp://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



eircQ 2010-10-11 15:55 发表评论
]]>
C语言字节寚w详解(?http://www.shnenglu.com/softko/archive/2010/09/17/126825.htmleircQeircQFri, 17 Sep 2010 01:49:00 GMThttp://www.shnenglu.com/softko/archive/2010/09/17/126825.htmlhttp://www.shnenglu.com/softko/comments/126825.htmlhttp://www.shnenglu.com/softko/archive/2010/09/17/126825.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/126825.htmlhttp://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>

eircQ 2010-09-17 09:49 发表评论
]]>
þһۺ| þþþAVרվ| þۺɫHEZYO| þۺϾƷþ| þۺϾþ߾Ʒ| ѾþҹƷ| Ʒ91þþþþþ| ƷþþþþþþþĻ| պƷרþþ| þˬˬƬAV| Ʒ99þþƷ| þҹҹݺ| ޹Ʒһþ| ձƷþþþþþþ| þer99ȾƷһ| 2021þþƷѹۿ| ݺݾƷþþĻ| ƷþþĻ| 99þ˾ƷۺϹۿ| ޵һƷƷþ | 2021ƷþþƷ| þþƷֻоƷ66| ޹ŷۺϾþ| þþ޾Ʒһ| þ96Ʒþþ| þۺ88| ޹Ʒþþò| þþ޾Ʒһ| Ƶþ| Ʒһþ㽶߿| þù鶹91| 9þ9þþƷ| ŮþþƷ㽶69| aaaƷþþùƬ| ޹ƷþSM | 뾫Ʒþһ| þƵ1| պavþþƷ| ޾Ʒһþ| ھƷ˾þþþ777| þAAAƬ69|