勤能补拙,Expter

成都游戏Coder,记录游戏开发过程的笔记和心得!

#

WPARAM与LPARAM的区别

具体是这么说:“在Win 3.x中,WPARAM是16位的,而LPARAM是32位的,两者有明显的区别。因为地址通常是32位的,所以LPARAM 被用来传递地址,这个习惯在Win32 API中仍然能够看到。在Win32 API中,WPARAM和LPARAM都是32位,所以没有什么本质的区 别。Windows的消息必须参考帮助文件才能知道具体的含义。如果是你定义的消息,愿意怎么使这两个参数都行。但是习惯上,我们愿意使用LPARAM传 递地址,而WPARAM传递其他参数。”


看一个例子就明白了:  程序代码*在对话框中取出数据,并向其他窗口发送消息和数据,将数据指针作为一个参数发送*/
void CTestDlg2::OnCommBtn()
{
     char szOut[30];
      GetDlgItemText(IDC_OUT,szOut,30);
      m_pParent->SendMessage(WM_DLG_NOTIFY,(WPARAM)szOut);
}

/*在消息接收窗口中*/
/*映射消息处理函数*/
ON_MESSAGE(WM_DLG_NOTIFY,OnDlgNotifyMsg)

/*在视图中绘制出字符串 m_szOut*/
void CMy53_s1View::OnDraw(CDC* pDC)
{
      CMy53_s1Doc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
     // TODO: add draw code for native data here
      pDC->TextOut(0,0,"Display String");
      pDC->TextOut(0,20,m_szOut);
}
/*处理通知消息,保存信息并更新显示*/
LONG CMy53_s1View::OnDlgNotifyMsg(WPARAM wP,LPARAM lP)
{
      m_szOut=(char*)wP;
      Invalidate();
     return 0;
}

一个字符串的地址通过WPARAM来标识,再通过Windows消息发送出去;之后在消息处理函数中WPARAM接受到的参数就是该地址,然后就可以对该地址进行操作了~~~

这是Windows消息机制中经常用到的两个data type,呵呵。

posted @ 2008-12-24 10:04 expter 阅读(12363) | 评论 (2)编辑 收藏

一些笔试题(包括金山西山居笔试)

以前做过的笔试题,都是自己曾经做的


# include <iostream>
using namespace std;
#define Q(x)  x*x
int main()
{
    
int a =10;
    
int b = 2;
    
int c = 1;

    a 
/=Q(b+c)/Q(b+c);

    cout 
<< a <<endl;
    
return 0;
}


因为 宏Q(x) 不规范,
所以结果 很迷惑人

a   /=Q(b+c)/Q(b+c);的执行顺序是从右到左

tmp = Q(b+c)/Q(b+c) =  2+1*2+1 / 2+1*2+1 =2+2+0+2+1=7  没有对宏加括号是经常容易犯错!

a = a/tmp = 10/7 = 1

所以  a = 1;








-----------------------------------------

题目2
反转一个字符串(西山居笔试题):
题目:写一个函数,把一个以0字符结尾的字符串str中的'A'字符移到str的末尾!

分析:
1:以时间换空间   从后向前循环查找字符A
2:以空间换时间   一次循环

算法1代码:

void Deal(char *str )
{
    
int len = strlen(str);
    
int a= len-1,b=0;
    
if (str[a] != '0')
    
{
        
return;             //如果最后一个字符不为'0'
    }

    
while (a>=0)
    
{
        
if (str[a] == 'A')
        
{
            
int n = a;
            
while (n < len-b-1)
            
{
                str[n] 
= str[n+1];  //
                n++;
            }

            str[n] 
='A';
            b
++;           //b累加,表示有b个字符A
        }

        a
--;
    }

}




算法2:
void Deal(char *str )
{
    
int len = strlen(str);
    
int a= len-1,b=0,i=0,j=0;
    
if (str[a] != '0')
    
{
        
return;             //如果最后一个字符不为'0'
    }

    
char * tmp = new char[len+1];
    
while(i<len)
    
{
        
if(str[i] !='A')
            tmp[j
++= str[i];
        
else
            b
++;          //多少个字符A
        i++;
    }


    
while (j<len)
    
{
        tmp[j
++= 'A';
    }

    tmp[len] 
= '\0';
    strcpy(str,tmp);

    
    delete tmp;   
//释放空间
    tmp = NULL;
}




PS:因为是直接手写的。。所以难免有错误!
现在修改了,对不起各位。。。

posted @ 2008-12-22 22:24 expter 阅读(5870) | 评论 (14)编辑 收藏

毕业前---最近看的书

  明年过年就要上班了,最近看了 effective c++ 和  more effective c++
 
 今天有去图书馆借了3本书,准备回家过年看,

  这3本书为 C++编程艺术 , exceptional c++ style , OOD启示录
  都是传说的好书,但是对于每一个来说不一定是好书, 先看完在说。。


其中Wesley的effective c++ 和  more effective c++ 的确不错,加深了对c++的认识,以及OO的理解,项目中应该注意的问题!

 加油咯,就要迈入社会了!


posted @ 2008-12-22 22:05 expter 阅读(297) | 评论 (1)编辑 收藏

心情沉重啊!

sohu被刷了。。
哎!

还是踏实点 好好学习吧!

现在的心情除了失落没有设么词形容了

posted @ 2008-12-19 21:33 expter 阅读(240) | 评论 (0)编辑 收藏

添加一个yahoo的统计代码,

posted @ 2008-12-14 20:52 expter 阅读(124) | 评论 (0)编辑 收藏

广播实现代码

首先 UDP 默认不能实现广播
要实现一个机子的广播,首先 应该明白2个函数
     1.setsockopt 开启发送广播报文
     2.getsockopt 确定广播选项是否关闭

setsockopt 的原型定义:
WINSOCK_API_LINKAGE int WSAAPI setsockopt( IN SOCKET s, IN int level, IN int optname, IN const char FAR * optval, IN int optlen )
开启报文代码

if (setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&bborad,oplen) == SOCKET_ERROR)
    {
        printf(
"setsockopt error!");
        
return 0;
    }

作为server:
然后发送广播报文
    sockaddr_in addr;
    
int nlen = sizeof(addr);
    memset(
&addr,0,nlen);

    addr.sin_family 
= AF_INET;
    addr.sin_port 
= htons(9999);
    addr.sin_addr.s_addr 
=INADDR_BROADCAST;

    
const char *msg = "hello! This is a test!";
    
int len = strlen(msg);

    
if (sendto(sock,msg,len,0,(struct sockaddr *)&addr,sizeof(addr)) == SOCKET_ERROR)
    {
        printf(
"send error !!");
        
return 0;
    }


然后客户端:
接受报文:
2008年12月8日
# include <WinSock2.h>
# include 
<stdio.h>

#pragma   comment(lib,   
"ws2_32.lib")
#define WSVERS MAKEWORD(2,0)
//CInitSock initSock;
int main()
{
    WSADATA wsadata; 
    
    
if(WSAStartup(WSVERS,&wsadata))
    {
        printf(
"WSAStartup failed!\n");
        
        
return 0;
    }
    SOCKET sLiten 
= ::socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    
if(sLiten == INVALID_SOCKET)
    {
        printf(
"WSACleanup failed with error %d\n",WSAGetLastError());
        
//printf(" Failed socket()");
        return 0;
    }
    
    sockaddr_in local;
    local.sin_family 
= AF_INET;
    local.sin_port 
= htons(9999);
    local.sin_addr.s_addr 
=INADDR_ANY;
    
    
if(::bind(sLiten,(LPSOCKADDR)&local,sizeof(local)) == SOCKET_ERROR)
    {
        printf(
" failed bind()");
        
return 0;
    }
    
    
char buf[1024];
    sockaddr_in addr;
    
int nlen = sizeof(addr);
    
    
while(1)
    {
        
int recv = ::recvfrom(sLiten,buf,1024,0,(sockaddr *)&addr,&nlen);
        
if(recv )
        {
            buf[recv] 
= '\0';
            printf(
"接收到数据  (%s): (%s)",::inet_ntoa(addr.sin_addr),buf);
        }
    }
    ::closesocket(sLiten);
    
return 0;
}


posted @ 2008-12-08 10:44 expter 阅读(1756) | 评论 (0)编辑 收藏

转:郑州招聘会 触目惊心图片背后究竟发生了什么

朋友发来一张图片,是大学生招聘的现场画面。看后竟无语以对。究竟发生了什么?看看通用、福特、克莱斯勒在破产边缘挣扎,雷曼兄弟轰然倒塌,今天英国最大的零售连锁Woolworths一英磅没人收购,宣布破产,还有更多的破产倒闭在继续,中国中小企业上半年已有近7万家倒闭。同样华尔街的金融危机正迅速演变成经济危机,这个笼罩在不少人不愿触及的敏感话题面纱正快速被撕掉,冬天刚刚开始。

在复杂的国际形势和恶劣的经济环境下,独善其身的企业也不能侥幸。同样任何行业都必须为这此金融海啸埋单,包括银行。前几天我在回答和讯网马上访谈的栏目记者采访时,进一步提出“家电下乡”大跃进的危机所在,然而大量网友的指责并不能解除家电制造商脸上的尴尬。一方面来自渠道连锁的积怨已经爆发,另一方面内需的刺激几乎脱离了实际,还有内外交困的市场环境在一步步逼近并影响到其它行业。毫无疑问,矛盾在上升,众多的不确定性将在2009年1月-5月发生,不仅仅是将有更多的企业破产消逝,一系列社会问题也将考验我们每一个人。

这些图片说明什么?其背后究竟发生了什么?几乎每一个人都会异口同声地想到一点那就是就业形势的严峻,然而这只是其一,真正的原因还有经济形势不容乐观,企业竞争力在衰减,市场需求在减少,通涨通缩的变化太快,中国教育的垢病凸显愈加清晰。等等。但我们是否问过自己,究竟是谁导演了这一切?










        



posted @ 2008-12-08 10:34 expter 阅读(2991) | 评论 (6)编辑 收藏

STL 中 map和set的区别

stl中:
MAP的节点是一对数据.  
SET的节点是一个数据.

Map使用关键值Key来唯一标识每一个成员 map可以重复。
set是集合   

                                   
都属于关联容器  
只不过,   map的形式   map<type1,   type2>   mymap;  
           set的形式   set<type>   myset;  


set(集合)——包含了经过排序了的数据,这些数据的值(value)必须是唯一的。

map(映射)——经过排序了的二元组的集 合,map中的每个元素都是由两个值组成,其中的key(键值,一个map中的键值必须是唯一的)是在排序或搜索时使用,它的值可以在容器中重新获取;而 另一个值是该元素关联的数值。比如,除了可以ar[43] = "overripe"这样找到一个数据,map还可以通过ar["banana"] = "overripe"这样的方法找到一个数据。如果你想获得其中的元素信息,通过输入元素的全名就可以轻松实现。

map是映射集合中的元素不能重复,set可以进行集合的各种操作(交并补等),当然你也可以用list或vector实现set,但是效率会很低。set一般是用平衡树或哈西表实现的。
映射是一种一一对应的关系,哈西表也可以看作是映射的一种。映射通常可用来实现字典结构(dictionary)





posted @ 2008-12-06 10:43 expter 阅读(7724) | 评论 (0)编辑 收藏

09年我曾经遇到的笔试题目

1.指针运算

注意 ,每个例子不只是一个题目,可能有多个,用//....................................来分开的
# include <iostream>
# include 
<stdio.h>
using namespace std;

enum string
{
    x1,x2,x3
=10,x4,x5,
}X;

int main()
{
    
//测试1
   
    cout << x1 << x5<<endl;
    unsigned char *p1;
    unsigned long *p2;
    p1 = (unsigned char *)0x801000;
    p2 = (unsigned long *)0x801000;
    
    printf("%p\n",p1+5);
    printf("%p\n",p2+5);

    char * t [] = { "abccc","daa","caa"};
    char **bb = t;
    cout << t[1] <<endl;
    cout << sizeof(t)<<endl;
   


//....................................
    int a[5= {1,2,3,4,5};
    cout 
<< *( (int *)(&a+1)-2<<endl; 


                
int  i=0;
    
int  j=1;
    
long *= NULL;
    
char *= NULL;
    
if(j++ && i++)
        p
++,c++;
    
if(i++ || j++)
        p
++,c++;

    cout 
<< i <<" " << j << " " << *<< " " << (long *)c <<endl;


   
//....................................
    int i =1;
   
int c = (i++) + (i++) + (i++);

    cout 
<< c <<" "<< i<<endl;

    
return 0;
}

2.
# include <iostream>
# include 
<stdio.h>
using namespace std;

void foo(int k)
{
    
char tmp[100];
    
//sprintf(tmp,"%d",k);
    printf("%d\n",tmp);
    foo(k
-1);
}
int main()
{

    
int  i= 0;
    
int  x= 0;
    
int  y= 0;
    printf(
"%d %d %d %d\n",x--,++y,i++,i++); 
    
char tmp[20]="hello\0\t\\\\world";
    cout
<<tmp<<endl;
    cout 
<< sizeof(tmp) << " " <<strlen(tmp)<<" "<< tmp<<endl;

   
//....................................
    char arr[100]  = "hello world";
    
int  *= (int *)arr;
    v[
0= 0X61626364;
    v[
1= 0X41424344;
    v[
2= 0X31323334;
    v[
3= 0;
    cout
<<arr<<endl;
   
    //....................................
    foo(3);
    return 0;
}


posted @ 2008-12-06 10:27 expter 阅读(1161) | 评论 (2)编辑 收藏

KMP 算法笔记

KMP算法是查询子串比较快的一种算法!

我们先看普通的模式匹配算法。。
int Index(String S,String T,int pos)//参考《数据结构》中的程序
{
  i
=pos;j=1;//这里的串的第1个元素下标是1
  while(i<=S.Length && j<=T.Length)
  {
    
if(S[i]==T[j]){++i;++j;}
    
else{i=i-j+2;j=1;}//**************(1)
  }
  
if(j>T.Length) return i-T.Length;//匹配成功
  else return 0;
}
匹配的过程非常清晰,关键是当‘失配’的时候进行回溯!

看下面的例子:

S:aaaaabababcaaa  T:ababc

aaaaabababcaaa
    ababc.(.表示前一个已经失配)
回溯的结果就是
aaaaabababcaaa
     a.(babc)
如果不回溯就是
aaaaabababcaaa
        aba.bc
这样就漏了一个可能匹配成功的情况
aaaaabababcaaa
      ababc



为什么会发生这样的情况?这是由T串本身的性质决定的,是因为T串本身有前后'部分匹配'的性质。如果T为abcdef这样的,大没有回溯的必要。

改进的地方也就是这里,我们从T串本身出发,事先就找准了T自身前后部分匹配的位置,那就可以改进算法。

如果不用回溯,那T串下一个位置从哪里开始呢?

还是上面那个例子,T为ababc,如果c失配,那就可以往前移到aba最后一个a的位置,像这样:
...ababd...
   ababc
   ->ababc

这样i不用回溯,j跳到前2个位置,继续匹配的过程,这就是KMP算法所在。这个当T[j]失配后,j应该往前跳的值就是j的next值,它是由T串本身固有决定的,与S串无关。

《数据结构》上给了next值的定义:
          
0   如果j=1
next[j]
={Max{k|1<k<j且'p1pk-1'='pj-k+1pj-1'
          
1   其它情况

我当初看到这个头就晕了,其实它就是描述的我前面表述的情况,关于next[1]=0是规定的,这样规定可以使程序简单一些,如果非要定为其它的值只要不和后面的值冲突也是可以的;而那个Max是什么意思,举个例子:

T:aaab

...aaaab...
   aaab
  ->aaab
   ->aaab
    ->aaab

像这样的T,前面自身部分匹配的部分不止两个,那应该往前跳到第几个呢?最近的一个,也就是说尽可能的向右滑移最短的长度。

OK,了解到这里,就看清了KMP的大部分内容,然后关键的问题是如何求next值?先不管它,先看如何用它来进行匹配操作,也就是说先假设已经有了next值。

将最前面的程序改写成:

int Index_KMP(String S,String T,int pos)
{
  i
=pos;j=1;//这里的串的第1个元素下标是1
  while(i<=S.Length && j<=T.Length)
  {
    
if(j==0 || S[i]==T[j]){++i;++j;} //注意到这里的j==0,和++j的作用就知道为什么规定next[1]=0的好处了
    else j=next[j];//i不变(不回溯),j跳动
  }
  
if(j>T.Length) return i-T.Length;//匹配成功
  else return 0;
}

OK,是不是非常简单?还有更简单的,求next值,这也是整个算法成功的关键,从next值的定义来求太恐怖了,怎么求?前面说过了,next值 表达的就是T串的自身部分匹配的性质,那么,我只要将T串和T串自身来一次匹配就可以求出来了,这里的匹配过程不是从头一个一个匹配,而是从T[1]和T [2]开始匹配,给出算法如下:

void get_next(String T,int &next[])
{
  i
=1;j=0;next[1]=0;
  
while(i<=T.Length)
  {
    
if(j==0 || T[i]==T[j]){++i;++j; next[i]=j;/**********(2)*/}
    
else j=next[j];
  }
}
注意到(2)语句逻辑覆盖的时候是T[i]==T[j]以及i前面的、j前面的都匹配的情况下,于是先自增,然后记下来next[i]=j,这样每当i有 自增就会求得一个next[i],而j一定会小于等于i,于是对于已经求出来的next,可以继续求后面的next,而next[1]=0是已知,所以整 个就这样递推的求出来了,方法非常巧妙。

posted @ 2008-12-06 10:23 expter 阅读(251) | 评论 (0)编辑 收藏

仅列出标题
共7页: 1 2 3 4 5 6 7