#
具體是這么說:“在Win 3.x中,WPARAM是16位的,而LPARAM是32位的,兩者有明顯的區(qū)別。因為地址通常是32位的,所以LPARAM 被用來傳遞地址,這個習慣在Win32 API中仍然能夠看到。在Win32 API中,WPARAM和LPARAM都是32位,所以沒有什么本質的區(qū) 別。Windows的消息必須參考幫助文件才能知道具體的含義。如果是你定義的消息,愿意怎么使這兩個參數(shù)都行。但是習慣上,我們愿意使用LPARAM傳 遞地址,而WPARAM傳遞其他參數(shù)。”
看一個例子就明白了: 程序代碼*在對話框中取出數(shù)據(jù),并向其他窗口發(fā)送消息和數(shù)據(jù),將數(shù)據(jù)指針作為一個參數(shù)發(fā)送*/
void CTestDlg2::OnCommBtn()
{
char szOut[30];
GetDlgItemText(IDC_OUT,szOut,30);
m_pParent->SendMessage(WM_DLG_NOTIFY,(WPARAM)szOut);
}
/*在消息接收窗口中*/
/*映射消息處理函數(shù)*/
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消息發(fā)送出去;之后在消息處理函數(shù)中WPARAM接受到的參數(shù)就是該地址,然后就可以對該地址進行操作了~~~
這是Windows消息機制中經(jīng)常用到的兩個data type,呵呵。
明年過年就要上班了,最近看了 effective c++ 和 more effective c++
今天有去圖書館借了3本書,準備回家過年看,
這3本書為 C++編程藝術 , exceptional c++ style , OOD啟示錄
都是傳說的好書,但是對于每一個來說不一定是好書, 先看完在說。。
其中Wesley的effective c++ 和 more effective c++ 的確不錯,加深了對c++的認識,以及OO的理解,項目中應該注意的問題!
加油咯,就要邁入社會了!
sohu被刷了。。
哎!
還是踏實點 好好學習吧!
現(xiàn)在的心情除了失落沒有設么詞形容了

首先 UDP 默認不能實現(xiàn)廣播
要實現(xiàn)一個機子的廣播,首先 應該明白2個函數(shù)
1.setsockopt 開啟發(fā)送廣播報文
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:
然后發(fā)送廣播報文
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("接收到數(shù)據(jù) (%s): (%s)",::inet_ntoa(addr.sin_addr),buf);
}
}
::closesocket(sLiten);
return 0;
}
stl中:
MAP的節(jié)點是一對數(shù)據(jù).
SET的節(jié)點是一個數(shù)據(jù).
Map使用關鍵值Key來唯一標識每一個成員 map可以重復。
set是集合
都屬于關聯(lián)容器
只不過, map的形式 map<type1, type2> mymap;
set的形式 set<type> myset;
set(集合)——包含了經(jīng)過排序了的數(shù)據(jù),這些數(shù)據(jù)的值(value)必須是唯一的。
map(映射)——經(jīng)過排序了的二元組的集
合,map中的每個元素都是由兩個值組成,其中的key(鍵值,一個map中的鍵值必須是唯一的)是在排序或搜索時使用,它的值可以在容器中重新獲取;而
另一個值是該元素關聯(lián)的數(shù)值。比如,除了可以ar[43] = "overripe"這樣找到一個數(shù)據(jù),map還可以通過ar["banana"] =
"overripe"這樣的方法找到一個數(shù)據(jù)。如果你想獲得其中的元素信息,通過輸入元素的全名就可以輕松實現(xiàn)。
map是映射集合中的元素不能重復,set可以進行集合的各種操作(交并補等),當然你也可以用list或vector實現(xiàn)set,但是效率會很低。set一般是用平衡樹或哈西表實現(xiàn)的。
映射是一種一一對應的關系,哈西表也可以看作是映射的一種。映射通常可用來實現(xiàn)字典結構(dictionary)
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 *p = NULL;
char *c = NULL;
if(j++ && i++)
p++,c++;
if(i++ || j++)
p++,c++;
cout << i <<" " << j << " " << *p << " " << (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 *v = (int *)arr;
v[0] = 0X61626364;
v[1] = 0X41424344;
v[2] = 0X31323334;
v[3] = 0;
cout<<arr<<endl;
//....................................
foo(3);
return 0;
}
KMP算法是查詢子串比較快的一種算法!
我們先看普通的模式匹配算法。。
int Index(String S,String T,int pos)//參考《數(shù)據(jù)結構》中的程序
{
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.(.表示前一個已經(jīng)失配)
回溯的結果就是
aaaaabababcaaa
a.(babc)
如果不回溯就是
aaaaabababcaaa
aba.bc
這樣就漏了一個可能匹配成功的情況
aaaaabababcaaa
ababc
為什么會發(fā)生這樣的情況?這是由T串本身的性質決定的,是因為T串本身有前后'部分匹配'的性質。如果T為abcdef這樣的,大沒有回溯的必要。
改進的地方也就是這里,我們從T串本身出發(fā),事先就找準了T自身前后部分匹配的位置,那就可以改進算法。
如果不用回溯,那T串下一個位置從哪里開始呢?
還是上面那個例子,T為ababc,如果c失配,那就可以往前移到aba最后一個a的位置,像這樣:
...ababd...
ababc
->ababc
這樣i不用回溯,j跳到前2個位置,繼續(xù)匹配的過程,這就是KMP算法所在。這個當T[j]失配后,j應該往前跳的值就是j的next值,它是由T串本身固有決定的,與S串無關。
《數(shù)據(jù)結構》上給了next值的定義:
0 如果j=1
next[j]={Max{k|1<k<j且'p1
pk-1'='pj-k+1
pj-1'
1 其它情況
我當初看到這個頭就暈了,其實它就是描述的我前面表述的情況,關于next[1]=0是規(guī)定的,這樣規(guī)定可以使程序簡單一些,如果非要定為其它的值只要不和后面的值沖突也是可以的;而那個Max是什么意思,舉個例子:
T:aaab
...aaaab...
aaab
->aaab
->aaab
->aaab
像這樣的T,前面自身部分匹配的部分不止兩個,那應該往前跳到第幾個呢?最近的一個,也就是說盡可能的向右滑移最短的長度。
OK,了解到這里,就看清了KMP的大部分內容,然后關鍵的問題是如何求next值?先不管它,先看如何用它來進行匹配操作,也就是說先假設已經(jīng)有了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的作用就知道為什么規(guī)定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,于是對于已經(jīng)求出來的next,可以繼續(xù)求后面的next,而next[1]=0是已知,所以整
個就這樣遞推的求出來了,方法非常巧妙。