׃息位产生冗余位的~码q程,是已知K(X)求R(X)的过E。在CRC码中可以通过扑ֈ一个特定的rơ多式G (X)(其最高项Xr的系数恒?),然后用Xr·K(X)去除以G(X),得到的余式就是R(X)。特别要的是,q些多项式中?+"都是??也即异或q算);此外,q里的除法用的也是模2除法,即除法过E中用到的减法是?减法,它和?加法的运规则一?都是异或q算,q是一U不考虑加法q位和减法借位的运??/p>
0+O=0,0+1=1,1+0=1,1+1=0
0-0=0,0-1=1,1-0=1,1-1=0
在进行基于模2q算的多式除法?只要部分余数首位?,便可上商1,否则上商0。然后按?减法求得余数,该余C计最高位。当被除数逐位除完?最后得到比除数一位的余数。此余数即ؓ冗余?其d在信息位后便构成CRC码字?br /> 仍以上例中K(X)=X6+X4+X3+1Z(即信息位?011001),若G(X)=X4+X3+1
(对应代码11001),取r=4,则X4·K(X)=X10+X8+X7+X4(对应代码?110010000),其由?除法求余式R(X)的过E所C如?
得到的最后余Cؓ1010,q就是冗余位,对应R(X)=X3+X?br /> ׃R(X)是Xr·K(X)除以G(X)的余?那么下列关系式必然满?br /> Xr·K(X)=G(X)Q(X)+R(X)
其中Q(X)为商式。根据模二运规则R(X)+R(X)=0的特?可将上式改记?/p>
[Xr-K(X)+R(X)]/G(X)=Q(X)
? T(X)/G(X)=Q(X)
由此可见,信道上发送的码字多项式T(X)=Xr-K(X)+R(X)。若传输q程无错Q则接收Ҏ到的码字也对应于此多式,也即接收到的码字多项式能被G(X)整除。因而接收端的校验过E就是将接收到的码字多项式除以G(X)的过E。若余式为零则认Z输元差错;若余式不为零则传输有差错?/p>
例如,前述例子中若码字10110011010l传输后׃受噪声的q扰,在接收端变成?0110011100,则求余式的除法如?
求得的余式不为零,相当于在码字上面半加上了差错模式00000000110。差错模式对应的多项式记为E(X),上例中E(X)=X2+X。有差错?接收端收到的不再是T(X),而是T(X)与E(X)之模二加,?br /> [T(X)+E(X)]/G(X)=T(X)/G(X)+E(X)/G(X)
若E(X)/G(X)=0,则这U差错就能检出?若E(X)/G(X)=0,那么׃接收到的码字多项式仍然可被G(X)整除,错误检不出来,也即发生了漏?/p>
理论上可以证明@环冗余校验码的检错能力有以下特点:
(1)可检出所有奇C错?br /> (2)可检出所有双比特的错?br /> (3)可检出所有小于、等于校验位长度的突发错?/p>
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=582980
1Q消息响应函敎ͼQ例Q在CDrawViewcd应鼠标左键按下消息)
1Q在头文?DrawView.h)中声明消息响应函数原型?br />//{{AFX_MSG(CDrawView) //注释?br />afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG //注释?br />说明Q?br />在注释宏之间的声明在VC中灰色显C。afx_msg宏表C声明的是一个消息响应函数?
q个注释宏ؓ的是让ClassWizard能够分L出哪些代码是它生成的Q哪些是你自己写的?br />你自己写的代码要在这个注释之外,q样ClassWizard再修Ҏ息映的时候就不会你的代码了?br />限于以前的硬仉度QClassWizard比较dQ所以需要这些注释宏来定位。从7.0开始,׃再需
要了。新的属性页能够自动分析你的代码Qؓ你添加或者删除代码,而无需什么特D标记的帮忙?br />因此注释宏已l是历史产物了?/p>
2Q在源文ӞDrawView.cpp)中进行消息映?br />BEGIN_MESSAGE_MAP(CDrawView, CView)
//}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
说明Q?br />在宏BEGIN_MESSAGE_MAP()与END_MESSAGE_MAP()之间q行消息映射?br />宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN与它的响应函数OnLButtonDownQ)相关联。这样一旦有消息的生,׃自动调用相关联的消息响应函数d理?br />宏ON_WM_LBUTTONDOWN()定义如下Q?br />#define ON_WM_LBUTTONDOWN()
{ WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp,
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnLButtonDown },
3Q源文g中进行消息响应函数处理。(DrawView.cpp中自动生成OnLButtonDown函数轮廓Q如下)
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
说明Q?br />可见当增加一个消息响应处理,在以上三处进行了修改。可在消息响应函数里d消息处理代码完成Ҏ息的响应、处理?/p>
2Q消息响应的方式Q?br />1Q?
在基cM针对每种消息做一个虚函数Q当子类Ҏ息响应时候,只要在子cM重写q个虚函数即可。缺点:MFCcL生层ơ很多,如果在基cd每个消息q行虚函
数处理,那么从基cL生的每个子类都将背负一个庞大的虚表Q这h费内存,故MFC没有采取q中方式而采取消息映方式?br />2Q消息映方式:
MFC在后台维护了一个句柄和C++对象指针对照表,当收C个消息后Q通过消息l构里资源句柄(查对照表Q就可找C它对应的一个C++对象指针Q然?
把这个指针传l基c,基类利用q个指针调用WindowProc()函数Ҏ息进行处理,WindowProc()函数中调用OnWndMsg()函数Q?
真正的消息\由及处理是由OnWndMsg()函数完成的。由于WindowProc()和OnWndMsg()都是虚函敎ͼ而且是用zcd象指针调?
的,由多态性知最ȝ调用子类的。在OnWndMsg()函数处理的时候,Ҏ消息U类L找消息映,判断所发的消息有没有响应函敎ͼ具体方式是到相关
的头文g和源文g中寻找消息响应函数声明(从注释宏//}AFX_MSG之间LQ,消息映射Q从宏BEGIN_MESSAGE_MAP(...)....END_MESSAGE_MAP()之间LQ,最l找到对应的消息处理函数。当Ӟ如果子类中没有对消息q行处理Q则消息交由基类处理?br />说明Q?br />virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
wxWidgets的文档中都是使用在控刉?数据源中讑֮DSN来创建ODBCq接。但是实际上很多型的应用,只是使用本机的一个Access数据库。而要求用者学习ODBC的DSN配置明显的增加了软g的用难度。因此,研究了一下wxforum.org中的帖子Q试验成功!范例如下Q?/p>
wxDbConnectInf *DbConnectInf = NULL; // 定义数据库连接信息指针DB connection information
wxDb *PodDB = NULL; // 定义数据库连接指针Database connection
wxDbTable *table = NULL; // 定义数据表指针Data table to access
DbConnectInf = new wxDbConnectInf(0, wxT(""), wxT(""), wxT(""));//q里定义的内容基本没用,但不定义会报?/p>
PodDB = new wxDb(DbConnectInf->GetHenv());
bool DBfailOnDataTypeUnsupported=!true;//
if(!DB->Open(wxT("DRIVER=Microsoft Access Driver (*.mdb);DBQ=D:\\pod.mdb;UID=admin;"),DBfailOnDataTypeUnsupported))//使用驱动E序的方式打开数据?br />{
if (PodDB->IsOpen())
{
// Connection is open, but the initialization of
// datatypes and parameter settings failed
return 0;
}
else
{
// Error opening datasource
//return HandleError(wxT("DB ENV ERROR: Cannot allocate ODBC env handle"));
return 0;
}
}
const wxString tableName = wxT("POD"); //定义要操作的表的名称
const UWORD numTableColumns = 8; //指出POD表中的列敎ͼcolumnsQ?br />//建立到表的连?br />table = new wxDbTable(PodDB, tableName, numTableColumns, wxT(""), wxDB_QUERY_ONLY, wxT(""));
//存放提取数据的变量清空
wxStrcpy(pPodPictureInfo->Title, wxT(""));
......
//定义列的数据格式Q和取出的格式?br />//此处需要注意的是如果前面指明了numTableColumns为n的话Q就一定要定义n?br />table->SetColDefs(0, wxT("Pod_Title"), DB_DATA_TYPE_VARCHAR, pPodPictureInfo->Title, SQL_C_WXCHAR, sizeof(pPodPictureInfo->Title), true, true);
......
//打开?br />if (!table->Open())
{
//An error occurred opening (setting up) the table"));
}
//限定取出Pod_When列gؓ1982的行(row)
table->SetWhereClause(wxT("Pod_When = '1982'"));
//按照PodDate字段排序
table->SetOrderByClause(wxT("Pod_Date"));
//Ҏ上面的限定信息执行查询操?br />if (!table->Query())
{
return HandleError(wxT("QUERY ERROR: "), table->GetDb());
//return 0;
}
while (table->GetNext())//提取查询到的?br />{
wxString msg; // Used for display messages
msg.Printf(wxT("Row #% lu --\nTitle : %s\nPodDate : %s\nWhere : %s\nWhen : %s\nWho : %s\nDisc : %s\nRelated : %s\nPhotoName :%s"),
table->GetRowNum(),
pPodPictureInfo->Title,
pPodPictureInfo->PodDate,
pPodPictureInfo->Where,
pPodPictureInfo->When,
pPodPictureInfo->Who,
pPodPictureInfo->Disc,
pPodPictureInfo->Related,
pPodPictureInfo->PhotoName
);
//查表操作/现实获取的POD信息
//wxSafeShowMessage(wxT("Pod_wxDbTable Test"),msg);
}
------补充一?-----
在SetColDefs中关联的变量不能使用wxStringQ只能用wxChar[n]{格式?/p>
struct PodPictrueInfo
{
wxChar Title[100];
......
}