VC++软件课程设计报告

通信与信息工程学院

2010 /2011  学年  第 2 学期

课程设计  实验报告

   

模  块  名  称   VC++软件设计

专          业     电子信息工程    

学  生  班  级      B090110        

学  生  学  号                      

学  生  姓  名                      

指  导  教  师       董恒        

日 期          2012   年  5  月

实验内容

    本课程设计分成练习题和综合题两部分。基础练习题11道中每个学生选择5个完成,要求如下:必做:1;2,3选择其一;4,5选择其一;6- 11选择其二。综合课题任选一道。

一 、 练习题:

1、基本环境调试

将例程1用VC++打开,修改错误使程序能够运行。理解编译错误,运行错误等。

2、文件操作

写一个档案文件保存以下内容:

学生姓名,性别,年龄,家庭住址,电话,电子邮件,爱好等。

再以上基础上进行该文件的读出并可编辑浏览显示。

3、图形编程

提供一个图形工具界面,让用户能够画出直线,椭圆,多边形等几何元素,结果可以保存并可读出。

4、字符串操作

能够从磁盘上选择打开文本文档,读入所有内容并显示,统计所有的字符数目,单词数目,中文字符串的数目。

5、动态链接库

目的:了解MFC支持的三种动态链接库:Win32DLL,MFC常规DLL, MFC扩展库。掌握封装DLL的基本方法。

二、综合题:

文件编辑

创建一个多文档工程,实现对于磁盘文件的浏览,编辑等功能。

能够以文本文件,二进制文件方式打开文件;

支持剪贴板功能;

支持搜索,查找,替换功能;

支持文件定位;

基本步骤:

(1)数据库后台设计,数据准备;

(2)界面设计;

(3)功能实现;

(4)测试。

实验环境

VC++ 6.0

实验步骤

               基础题

题目1 基本环境调测

1.1实验目的:

该程序计算任意数目以内的素数并且输出,要输入范围参数。修改给出的这段程序,使之能够运行,理解编译错误,运行错误等。

1.2程序说明:

本题是一道改错题,根据已经给出的例程1进行改错及完善的操作。打开VC++6.0,将例程1打开,点编译时会提示有


根据错误所在行数,分析代码修改代码,其中的一个错误是error 是C2106: '=' : left operand must be l-value混淆了逻辑的等于号和赋值的等号;还有的error 是C2181: illegal else without matching if,if少了一个配套的大括号。重新编译,链接都没有错误,在运行的时候,当输入100,200等较大的数求所有素数时出现下面的状况:只需将存放素数的数组容量变大,变为Primes[200]或更大

1.3测试结果:

总结分析:在调试的过程中,通过双击错误提示很轻松的将前两个编译错误很容易改出来了,存放素数的数组定义的太小而导致的问题则比较隐蔽,通过这个题目我对compiling,linking,build有了进一步的理解。

1.4程序:

void CFund1Dlg::OnButton1()

{

       UpdateData();

       int Primes[200];//存放素数的数组.

       int index=0;

    //简单的求素数算法.

       bool flag=true;

       for(int m=2;m<=m_limit;m++)

       {   

              for(int i=2;i<m;i++)

              {

                     if(m%i==0)

                     {

                            flag=false;

                            break;}

                    

                     else

                            flag=true;

              }

              if(flag==true)

                     Primes[index++]=m;

       }    

       CWnd *pWnd=GetDlgItem(IDC_STATICOUTPUT);

       CString str;

       str.Format("%d以内的素数有%d个:\n\n",m_limit,index);

       for(int i=0;i<index;i++){

              char buf[10];

              sprintf(buf,"%d ",Primes[i]);

              str+=buf;

       }

       pWnd->SetWindowText(str);

}

题目2 文件操作

2.1实验目的

1)        熟练掌握文件操作,学会用Write() 函数和Read()函数写文件和读文件

2)        学会建立MFC工程提供比较直观的对话框界面供浏览 

2.2程序说明:

   系统提供了一个控件面板,用鼠标选中我们需要的控件,将其放置对话框,设计出我们需要的程序界面。然后在建立类向导中为控件关联一个变量,分别为m_name,m_age,m_phone,m_email,m_address,m_hoppy,均为Cstring类型。然后就是编写控件消息处理函数,我们需要编写的是void CMyDlg::OnSave() ,void CMyDlg::OnOpen() ,分别对应控件“打开”“保存”,还需要编写voidCMyDlg::Display(StuInfo *si)显示函数。这样,这个程序的基本功能就满足要求了。

2.3流程图:

2.4测试结果:

总结分析:本题主要考察要求的是我们能否学会建立MFC工程提供比较直观的对话框界面供浏览,并编写相应的事件函数,以及熟练掌握文件操作,学会用Write() 函数和Read()函数写文件和读文件。

2.5关键程序:

//显示函数

void CMyDlg::Display(StuInfo *si)

{

       //StuInfo si=*m_StuIndex;

       m_name=si->name;

       m_age=si->age;

       m_phone=si->phone;

       m_email=si->email;

       m_hoppy=si->hoppy;

       m_address=si->address;

       UpdateData(FALSE);  //UpdateData(FALSE)是将控件的关联变量的值传给控件并改变控件状态

}

//保存函数

void CMyDlg::OnSave() 

{

       // TODO: Add your control notification handler code here

       UpdateData();   //UpdateData() 是MFC的窗口函数,用来刷新数据的

       StuInfo si;

       memset(&si,0,sizeof(StuInfo));  //memset() 函数常用于内存空间初始化

       strcpy(si.name,m_name);

       strcpy(si.phone,m_phone);

       strcpy(si.email,m_email);

       strcpy(si.address,m_address);

       strcpy(si.hoppy,m_hoppy);

       strcpy(si.age,m_age);

      

       // write into the file

       CFileDialog fileDlg(FALSE);

       fileDlg.m_ofn.lpstrFilter="Stud Info(*.si)\0*.si\0All Files(*.*)\0*.*\0\0";

       fileDlg.m_ofn.lpstrDefExt="si";

       if(IDOK==fileDlg.DoModal())

       {

              CFile file(fileDlg.GetFileName(), CFile::modeCreate | CFile::modeWrite);

              file.Write(&si, sizeof(StuInfo));

              file.Close();

       }

}

//打开文件函数

void CMyDlg::OnOpen()

{

       // TODO: Add your control notification handler code here

     CFileDialog fileDlg(TRUE);  //构造对话框对象(FALSE)表示保存(TRUE)表示打开

       fileDlg.m_ofn.lpstrFilter = "Stud Info(*.si)\0*.si\0All Files(*.*)\0*.*\0\0";

       if(IDOK==fileDlg.DoModal())//DoModal负责对模态话框的创建和撤销

       {

              CFile file(fileDlg.GetFileName(), CFile::modeRead);

              StuInfo si;

              file.Read(&si,sizeof(StuInfo));

              file.Close();

              Display(&si);

       }

}

void CMyDlg::OnAdd()

{

       // TODO: Add your control notification handler code here

       UpdateData();

       StuInfo stuinfo;

       memset(&stuinfo,0,sizeof(StuInfo));

       strcpy(stuinfo.name,m_name);

       strcpy(stuinfo.age,m_age);

       strcpy(stuinfo.phone,m_phone);

       strcpy(stuinfo.hoppy,m_hoppy);

       strcpy(stuinfo.email,m_email);

//     m_Records.push_back(stuinfo);

//     m_StuIndex=m_Records.end()-1;

题目三:图形编辑

3.1实验目的

1)掌握建立基于MFC的文档工程的步骤

2)熟悉鼠标绘图的机理,了解鼠标消息响应函数框架

3.2程序说明:

本题是使用MFC实现在界面上绘图的功能,基本包括点、直线、椭圆和矩形。关键问题是确定用户选择的图形类型,从而可以调用相应的类库,并将类实例化之后使用其中各种绘图函数。同时需要记录用户鼠标点击的操作,获取鼠标指针当前的屏幕坐标,确定图形的起始位置和结束位置。

3.3程序流程图

3.4测试结果:

结果分析:程序提供了一个图形绘制界面,我们可以画出直线,椭圆,矩形,绘制的结果可以通过文件中的保存并可通过“打开”读出原来原来已经保存的图形。要求我们能够熟悉鼠标绘图的机理,了解鼠标消息响应函数框架。

3.5关键程序:

void CGraphicView::OnDraw(CDC* pDC)

{

       CDrawDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

       if (!pDoc)

        return;

       int index;

       index = pDoc->m_ObArray.GetSize();//取得直线的数目

       for(int i=0;i<index;i++)

       {

              CShape * pShape = (CShape*) pDoc->m_ObArray.GetAt(i);

              pShape->Drawing(pDC);

       }

}

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

    this->last=point;

       CView::OnLButtonDown(nFlags, point);

}

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CDrawDoc *pDoc = GetDocument();

    pDoc->AddShape(last,point, m_sType);

       Invalidate();

       CView::OnLButtonUp(nFlags, point);

}

题目四:字符串的操作

4.1实验目的  

1)熟练掌握字符串处理

2)熟练掌握判断中文字符,英文单词的方法

3)掌握文件操作,如文件读取,文件存储

4)掌握MFC工程建立方法

4.2程序说明:

本题是对文本文件内的字符信息做统计工作。主要思想是通过嵌套判断来实现对字母,字符,汉字的区分。编写一个统计的函数Counting(char *p, int length)来统计,字符数numChar的大小由GetLength()得到,用if((p[i]>='a'&&p[i]<='z')||(p[i]>='A'&&p[i]<='Z'))判断是否是英文字母,因为我们知道英文单词的开头和结尾都是英文字符,我们不妨设置bool wordBeg = true,如果是,则numWord++,并且将wordBeg = false,这样判断完全部就能得到英文单词的数目了。再利用if(p[i]>=0x00&&p[i]<=0x7F)得到ASC码的数目,用总的字符数减去ASC码的数目就能得到中文字符数目的两倍(因为一个中文占两个字符)。这样所要求的都可以求出来了。

定义Display()和OnOpen()。把当前统计的数目分别赋给m_char,m_chinese,m_word,再通过UpdateData(FALSE) 将控件的关联变量的值传给控件并改变控件状态显示在窗口。OnOpen(),打开一个文本,CFileDialog fileDlg(TRUE);dwFileLen = file.GetLength(),用file.Read(pBuf, dwFileLen)读取dwFileLen长度的文件,用Close()关闭文件。

4.3程序流程图:


4.4测试结果:

总结分析:本题只要考察我们是否能够熟练掌握字符串处理,掌握判断中文字符,英文单词的方法掌握文件操作,如文件读取,文件存储掌握MFC工程建立方法。

4.5关键程序

void CMyDlg::OnOpen()

{

       // TODO: Add your control notification handler code here

       CFileDialog fileDlg(TRUE);   //构造对话框对象(FALSE)表示保存(TRUE)表示打开

       fileDlg.m_ofn.lpstrFilter="Text Files(*.txt)\0*.txt\0\0";

       if(IDOK==fileDlg.DoModal())

       {

              CFile file(fileDlg.GetFileName(), CFile::modeRead);

              char *pBuf;

              DWORD dwFileLen;

              dwFileLen = file.GetLength();  //长度

              // This the # of total char

              this->m_char= dwFileLen;

              pBuf = new char[dwFileLen];

              file.Read(pBuf, dwFileLen);

              file.Close();

              m_content =pBuf;

              Counting(pBuf, dwFileLen);

       }

}

void CMyDlg::Counting(char *p, int length)  //计算模块

{

       bool wordBeg = true;

       bool flag = true;

       int numAsc=0;

       this->m_word=0;

       for(int i=0; i<length; i++)

       {

              if((p[i]>='a'&&p[i]<='z')||(p[i]>='A'&&p[i]<='Z'))

              {

                     if(wordBeg)

                     {

                            this->m_word++;

                            wordBeg = false;

                     }

              }

              else   

              {

                     wordBeg = true;

              }

              if(p[i]>=0x00&&p[i]<=0x7F)

                     numAsc++;

       }

       this->m_chinese = (length-numAsc)/2;

       //this->numChar=length-numChinese;

       UpdateData(FALSE);

}

题目五:动态链接库

5.1实验目的

了解MFC 支持的三种动态链接库:Win32DLL,MFC 常规DLL, MFC扩展库。掌握封装DLL的基本方法。

5.2程序说明:

本题是使用动态链接库来完成一些简单的程序算法。动态链接库分为Win32、MFC及MFC扩展三种,分别通过不同的方法来建立。动态链接库编写完毕后,生成Dll和Lib文件,将其复制到测试工程的Debug文件夹下,并在工程中与Lib文件关联之后就可以调用动态链接库中的函数或方法

5.3测试结果:

总结分析:本题主要要求我们了解MFC 支持的三种动态链接库:Win32DLL,MFC 常规DLL, MFC扩展库,掌握封装DLL的基本方法。

5.4关键程序:

void CTestDLLDlg::OnButtonAdd()

{

       // TODO: Add your control notification handler code here

       HINSTANCE hInst;

       hInst=LoadLibrary("Win32DLL.dll");

       typedef int (*ADDPROC)(int a);

       ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");

       if(!Add)

       {

              MessageBox("获取函数地址失败");

              return;

       }

       UpdateData(TRUE);

       m_r1=Add(m_n);

       UpdateData(FALSE);

      

}

void CTestDLLDlg::OnButtonfactorial()

{

       // TODO: Add your control notification handler code here

       HINSTANCE hInst;

       hInst=LoadLibrary("MFCDLL.dll");

       typedef int (*ADDPROC)(int a);

       ADDPROC Jiechen=(ADDPROC)GetProcAddress(hInst,"Jiechen");

       if(!Jiechen)

       {

              MessageBox("获取函数地址失败");

              return;

       }

       UpdateData(true);

       m_r2=Jiechen(m_n2);

       UpdateData(FALSE);

}

二 、综合题。

实验目的:

首先创建一个多文档工程,实现对于磁盘文件的浏览,编辑等功能。能够以文本文件,二进制文件方式打开文件;支持剪贴板功能;支持搜索,查找,替换功能;功能参考了磁盘文件工具程序UltraEdit 。

程序说明:

功能要求分析:

1. 文件读取功能:

即利用目标系统能通过读取功能,一方面能够显示文件的原来数据形式,另一方面也能够把原来的数据形式通过编码转化为用户很方便识别的十六进制数据,进而为用户方便的了解文件的存储数据。

2. 文件编辑功能:

即利用目标系统能通过编辑功能,把对读取的文件数据进行修改,添加,删除,进而实现对原文件的更新的功能,以方便用户能够对文件的方便的操作。

3文件保存功能:

即利用目标系统能通过保存功能,把对读取的文件数据进行修改和编辑过后的数据在保存回原文件,以实现对原文件的保存

测试结果:

关键程序:

void CHexEditView::OnDraw(CDC* pDC)

{

       CRect rc;

       GetClientRect(rc);

       if(m_text == NULL)

       {

              pDC->FillRect(rc, &CBrush(RGB(255,255,255)));

              return;

       }

      

       CDC       dc;

       dc.CreateCompatibleDC(pDC);

       CBitmap bm;

       bm.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());

       dc.SelectObject(bm);

       dc.SetBoundsRect(&rc, DCB_DISABLE);

       CFont font;

       font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 );

       CFont* oldFont = dc.SelectObject ( &font );

       CBrush bkBrush(RGB(255,255,255));

    dc.FillRect(rc, &bkBrush);

      

       UINT lineCY, lineCX;

       UINT dwPos;

       char currentchar[20];

       UCHAR text[17];

       int lineBeginPos;

       m_HexStart = m_CharWidth * (14 - m_LeftChar);     //计算二进制显示开始位置

       m_TextStart = m_HexStart + m_CharWidth * 50;       //计算ASCII码显示开始位置

       for(UINT i = 0; i < m_PageRows; i++)               //按行显示数据

       {

              lineBeginPos = (m_TopLine+i-1)*16;                 //计算当前行开始字符相对于总缓冲区的位置

              lineCY = i * m_LineHeight;                              //当前行的Y坐标

              sprintf(currentchar, "%08Xh:", lineBeginPos);

              dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));

              dc.SetBkColor(RGB(255,255,255));

              dc.TextOut (m_CharWidth*(2-m_LeftChar), lineCY, currentchar);     //显示地址基值

              memcpy(text,&m_text[lineBeginPos],16);   //取当前行数据

              text[16] = '\0';

              for(int l = 0; l < 16; l++)

              {

                     if(text[l] < 32)

                            text[l] = 46;    //不可见ASCII字符用.表示

              }

              if(lineBeginPos+16 > m_CharCount)

              {

                     text[m_CharCount%16] = '\0';      //最后的数据不满一行时

              }

             

              dc.TextOut (m_TextStart, lineCY, text);//显示右面的ASCII字符

              //被选中时反色显示右面的ASCII字符

              int selStart = (m_SelStart - lineBeginPos)<0? 0:(m_SelStart - lineBeginPos);

              int selEnd = (m_SelEnd - lineBeginPos)>15? 15:(m_SelEnd - lineBeginPos);

              if(selStart <= 15 && selEnd >= 0)

              {

                     dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));

                     dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));

                     text[selEnd+1]='\0';

                     dc.TextOut (m_TextStart+selStart*m_CharWidth, lineCY, &text[selStart]);

              }

              else

              {

                     dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));

                     dc.SetBkColor(RGB(255,255,255));

              }

              for(UINT j = 0; j < 16; j++)

              {

                     dwPos = j + lineBeginPos;

                     if(dwPos > (m_CharCount-1))

                            goto bitblt;                   //显示完最后一行退出

                    

                     if(dwPos >= m_SelStart && dwPos <= m_SelEnd)

                     {

                            dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));

                            dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));

                     }

                     else

                     {

                            dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));

                            dc.SetBkColor(RGB(255,255,255));

                     }

                     lineCX = m_HexStart + j * m_CharWidth *3 ;                         //计算当前要显示的二进制字符的位置

                     sprintf(currentchar, "%02X", ((UCHAR *)m_text)[dwPos]);    

                     dc.TextOut (lineCX, lineCY, currentchar);                         //显示二进制字符

                     if(dwPos == m_SelEnd)                                                         //选中单个字符的显示

                     {

                            dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));

                            dc.SetBkColor(RGB(255,0,0));

                            UCHAR cHex = m_text[dwPos];

                            if(m_bFirst)//二进制字符的高四位选中

                            {

                                   cHex = cHex & 0xf0;

                                   cHex = cHex >> 4;

                                   sprintf(currentchar, "%X", cHex);

                                   dc.TextOut (lineCX, lineCY, currentchar);

                            }

                            else

                            {

                                   lineCX = m_HexStart + j * m_CharWidth *3 + m_CharWidth;

                                   cHex = cHex & 0x0f;

                                   sprintf(currentchar, "%X", cHex);

                                   dc.TextOut (lineCX, lineCY, currentchar);

                            }

                     }

              }

       }

bitblt:

       pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY);

       dc.DeleteDC ();}

小结

经过四周的c++软件设计,我能明显感受到我在编程语言的应用上有了显著提高。由于以前接触c++的时候基本是编写一个控制台应用程序,而这一次基本上是必须使用MFC编写。而对此我基本上就是第一次遇到,并且由于大一c++课程结束后就几乎没怎么碰过C++等原因,所以在实验周开始后我除了找出原来教材开始温故知新,我还去图书馆借了《可视化程序设计Visual C++》、《Visual C++程序设计实用案例教程》两本书。

一开始编程有许多不懂的或记得不带清楚的地方, 我就一一 翻书寻找答案解决问题。 随着一个一个困难的解决, 我的第一个程序终于可以完成题目所要求的功能。此外,咨询老师和其他同学也是十分必须的。来自于别人的帮助也十分重要,有时候别人的点拨和指导会让你茅塞顿开,帮助我们更准确的理解题意,比如动态链接库,那个开始根本让我摸不着头脑,经过别人的指导,就知道怎么入手了。

对于编程,我个人觉得,修改和程序的调试需要有细心和耐心。细心可以让我们发现微小的错误,耐心帮我们很好的解决这些错误。面对几百行代码,不断的设置断点,不断的调试,实在是一件很繁琐的事情。也许程序员的辛苦也在此处。但是,每当一个程序调试成功,都是那么地让人振奋人心。辛苦编写代码,修改,程序调试成功,一系列流程中都伴随着烦躁和耐心的较量。

在这四周的软件设计中我体会到失败的无耐,同时也体会到了成功的喜悦。 总的来说,这次程序设计使我受益匪浅,对程序设计有了进一步的认识,同时也认识到了自己的不足,今后我会更加努力学习程序设计为以后工作增添筹码。

相关推荐