21.插入排序算法实现
void insert (int a[],int n)
{
int i,j;
for(i=1;i<n;i++)
{
int x=a[i];
for(j=i;j>0&&x<a[j-1];j--)
a[j]=a[j-1];
a[j]=x;
}
}
22.快速排序算法实现
void quick (int a[],int ileft,int iright)
{
int iPivot=(left+right)/2;
int nPivot=a[iPivot];
for(int i=ileft,j=iright;i<j;)
{
while(!(i>=iPivot||nPivot<a[i]))
i++;
if(i<iPivot)
{
a[iPivot]=a[i];
iPivot=i;
}
while(!(j<=iPivot||nPivot>a[j]))
j--;
if(j>iPivot)
{
a[iPivot]=a[j];
iPivot=j;
}
}
a[iPivot]=nPivot;
if(iPivot-ileft>1)
quick (a,ileft,iPivot-1);
if(iright-iPivot>1)
quick (a,iPivot+1,iright);
}
23. 设计一个编辑控件的应用程序"EditBox."
(1)首先生成一个dialog-based的工程;
(2)在ResourceView选项卡中打开Dialog资源组,然后双击IDD_EDITBOX_DIALOG.
(3)利用控件窗口中的编辑框控件,在对话框中布置如上图所示的编辑框.将鼠标移到Edit1编辑框上-->单击鼠标右键,(在快捷菜单中)选择--> Properties命令,在窗口中输入控件的ID标识值,IDC_EDIT1,用同样的方法设置其它各个对象的属性.
(4) 给编辑框连接变量
(5)修改编辑框的特性
(6)添加代码
void CEditBoxDlg::OnShow1Button()
{
m_Edit1.SetSel(0,-1);
m_Edit.ReplaceSel("This is the firstEditBox.");
}
程序中SetSel()函数是CEdit类中的成员函数,因为m_Edit1是属于CEdit类的对象,故可以调用该类所有的成员函数.ReplaceSel()函数也是CEdit类中成员函数.
Void CEditBoxDlg::OnClearlButton()
{
m_Editl.SetSel(0,-1);//表示选中编辑框IDC_EDIT1中的全部内容.
m_Editl.ReplaceSel("");
}
Void CEditBoxDlg::OnShow2Button()
{
m_Edit2.SetSel(0,-1);//表示选中编辑框IDC_EDIT2中的全部内容.
m_Edit2.ReplaceSel("This is the secondEditBox.");
}
Void CEditBoxDlg::OnClear2Button()
{
m_Edit2.SetSel(0,-1);//表示选中编辑框IDC_EDIT2中的全部内容.
m_Edit2.ReplaceSel("");
}
void CEditBoxDlg()OnCopyButton()
{
m_Editl.SetSel(0,-1);
m_Editl.Copy();
m_Edit2.SetSel(0,-1)
m_Edit2.ReplaceSel("");
m_Edit2.Paste();
}
void CEditBoxDlg::OnUndoButton()
{
m_Edit1.Undo();//Undo()函数是CEdit类中的成员函数,表示取消编辑框中上一次操作
m_EdIT2.Undo();
}
void CEditBoxDlg::OnOKButton()
{
OnOK();
}
24. 多线程文件复制器:利用Windows标准多线程函数实现多线程文件复制
创建步骤:
1、 用AppWizard创建一个Dialog based空工程.
在"New"对话框中的"Projects"属性页中选择"MFCAppWizard(exe)"选项,在"Projectname"编辑框中输
入"FileCopy",然而单击"OK"按钮进入创建过程.在创建的第一步选择"Dialogbased"单选按钮,其它各
步接受缺省设置.
2、 增加资源.
双击ResourceView面板中的Dialog项,展开对话框资源列表.双击选择"IDD_FILECOPY_DIALOG"选项打
开主对话框.添加如下资源对话:
类型 ID Caption
Static TextIDC_STATIC 源文件:
Static TextIDC_STATIC 目标文件:
Edit box IDC_EDIT_SRC (无)
Button IDC_BUTTON_SRC …
Button IDC_BUTTON_DST …
Button ID_COPY 复制
Button IDCANCEL 关闭
3、编辑代码
(1)为菜单资源增加处理函数
在"ClassWizard"对话框中分别分别为ID_COPY、IDC_BUTTON_SRC、IDC_BUTTON_DST等按钮增加COMMAND
消息处理函数如下:
OnButtonSrc函数:用于显示"打开文件"对话框,帮助用户选择源文件,该函数实现如下:
void CfileCopyDlg::OnButtonSrc()
{
CfileDialog OpenFile(true);
OpenFile.DoModal();
CWnd* pEdit = GetDlgItem(IDC_EDIT_SRC);
PEdit->SetWindowText(OpenFile.GetPathName());
}
OnButtonDst函数: OnButtonDst函数用于显示"打开文件"对话框,帮助用户选择目的文件,该函数的实
现如下:
void CfileCopyDlg::OnButtonDst()
{
CfileDialog OpenFile(true);
OpenFile.DoModal();
CWnd* pEdit = GetDlgItem(IDC_EDIT_DST);
PEdit->SetWindowText(OpenFile.GetPathName());
}
OnCopy函数:用户单击"复制"按钮时,触发该函数.该函数用于创建新线程,实现如下:
void CfileCopyDlg::OnButtonCopy()
{
CfileDialog OpenFile(true);
OpenFile.DoModal();
CWnd* pEdit = GetDlgItem(ID_COPY);
PEdit->SetWindowText(OpenFile.GetPathName());
}
(2)增加线程函数
线程实际上是用特殊方法执行的函数,函数返回时,线程随即结束.本实例包含ReadFileData、WriteFileData、EndFileCopy等三个函数,为实现线程同步和数据交换,需定义如下变量:
char Buf1[BUFSIZ]; char Buf2[BUFSIZ];
int Buf1Size, Buf2Size;
HANDLE pRead1,pRead2;
HANDLE pWrite1,pWrite2;
HANDLE ReadThreadID,WriteThreadID,EndThreadID;
创建线程同步事件:当一个进程中有多个线程同时运行时,控制各线程的运行进度是实现线程间数据交换的关键,本程序使用线程事件同步线程.事件必须在使用前创建,程序在对象初始化时(OnInitDialog函数中)创建事件.
OnInitDialog函数修改如下:
BOOL CfileCopyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT((IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu !=NULL)
{
Cstring strAboutMenu;
StrAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);SetIcon(m_hIcon,FALSE); //创建线程同步事件
pRead1 =CreateEvent(NULL, true, false, "FileReadReady1");
pRead2 =CreateEvent(NULL, true, false, "FileReadReady2");
pWrite1=CreateEvent(NULL,true,false,"FileWriteReady1");
pWrite2=CreateEvent(NULL,true,false,"FileWriteReady2");
return TRUE;
}
ReadFileData函数:该函数是读文件线程,用于打开文件、读取数据,实现如下:
DWORDWINAPIReadFileData(LPVOIDlpParam)
{
FILE* fp;
Cstring FileName = (BSTR) lpParam;
::SysFreeString((BSTR) lpParam);
//初始化用户数据
Buf1Size = Buf2Size =BUFSIZ;
if (FileName.IsEmpty() ||!(fp = fopen(FileName, "rb")))
{
Buf2Size = Buf1Size =0;return 0;
}
for (; Buf2Size == BUFSIZ; )
{
WaitForSingleObject(pWrite1, INFINITE);
ResetEvent(pWrite1);
Buf1Size = fread(Buf1, 1,BUFSIZ, fp);
SetEvent(pRead1);
if (Buf1Size < BUFSIZ) break;
WaitForSingleObject(pWrite2, INFINITE);
ResetEvent(pWrite2);
Buf2Size = fread(Buf2, 1,BUFSIZ, fp);
}
fclose(fp);return 1;}
WriteFileData函数:该函数是写文件线程,用于写数据到目标文件中,实现如下:
DWORD WINAPI WriteFileData(LPVOIDlpParam)
{
FILE* fp;
Cstring FileName = (BSTR) lpParam;
::SysFreeString((BSTR) lpParam);
SetEvent(pWrite1);SetEvent(pWrite2);
if (FileName.IsEmpty() || !(fp = fopen(FileName, "wb"))) return 0;
for(; Buf1Size +Buf2Size >0; )
{
WaitForSingleObject(pRead1, INFINITE);
ResetEvent(pRead1);
fwrite(Buf1, Buf1Size, 1, fp);
SetEvent(pWrite1);
if(Buf1Size < BUFSIZ) break;
WaitForSingleObject(pRead2, INFINITE);
ResetEvent(pRead2);
fwrite(Buf2, Buf2Size, 1, fp);
SetEvent(pWrite2);
if(Buf2Size < BUFSIZ) break;
}
fclose(fp);
return 1;
}
EndFileCopy函数:用于判断访问文件线程的运行状态.当读、写线程结束时,通过线程返回值判断执行结果,该函数的实现如下:
DWORDWINAPIEndFileCopy(LPVOIDlpParam)
{
DWORD ReadThreadExitCord;
DWORD WriteThreadExitCord;
//WaitForSingleObject(ReadThreadID,INFINITE); //等待读进程结束
WaitForSingleObject(WriteThreadID,INFINITE); //等待写进程结束
TerminateThread(ReadThreadID, -1);
GetExitCodeThread(ReadThreadID,&ReadThreadExitCord);
GetExitCodeThread(WriteThreadID, &WriteThreadExitCord);
if(ReadThreadExitCord >0 &&WriteThreadExitCord > 0)
AfxMessageBox("文件复制完成");
else if (!ReadThreadExitCord)
AfxMessageBox("错误:源文件无法打开");
else
AfxMessageBox("错误:无法创建(更新)目标文件");
return 0;
}
25. 除字符串中所有给定的子串
问题描述:
在给定字符串中查找所有特定子串并删除,如果没有找到相应子串,则不作任何操作。
要求实现函数:
int delete_sub_str(const char *str, const char *sub_str, char *result_str)
【输入】 str:输入的被操作字符串
sub_str:需要查找并删除的特定子字符串
【输出】 result_str:在str字符串中删除所有sub_str子字符串后的结果
【返回】 删除的子字符串的个数
注:
I、 子串匹配只考虑最左匹配情况,即只需要从左到右进行字串匹配的情况。比如:
在字符串"abababab"中,采用最左匹配子串"aba",可以匹配2个"aba"字串。如果
匹配出从左到右位置2开始的"aba",则不是最左匹配,且只能匹配出1个"aba"字串。
II、 输入字符串不会超过100 Bytes,请不用考虑超长字符串的情况。
示例
输入:str = "abcde123abcd123"
sub_str = "123"
输出:result_str = "abcdeabcd"
返回:2
输入:str = "abcde123abcd123"
sub_str = "1234"
输出:result_str = "abcde123abcd123"
返回:0
View plaincopy to clipboardprint?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*删除字串函数,在src中删除sub子串,并将结果保存在result字符串中*/
int delSubStr(char * src,char * sub,char * result)
{
char * src_p=src;
char * sub_p=sub;
char * res_p=result;
int count=0;//记录包含子串的个数
int sub_len=strlen(sub);//记录子串的长度
char * temp;//临时保存子串的副本
temp=(char *)malloc(sub_len+1);
memset(temp,'\0',sub_len+1);
while(*src_p)
{
memcpy(temp,src_p,sub_len);
/*原串中包含与sub完全匹配的子串*/
if(!strcmp(temp,sub))
{
count++;
src_p+=sub_len;
}
else
*res_p++=*src_p++;
*res_p='\0';
free(temp);
return count;//返回包含子串的个数
}
}
void main()
{
char result[100];
int count=delSubStr("abcdefgde","de",result);
printf("The new string is:");
printf("%s\n",result);
printf("count is:");
printf("%d\n",count);
}
26. 高精度整数加法
问题描述:
在计算机中,由于处理器位宽限制,只能处理有限精度的十进制整数加减法,比如在32位宽处理器计算机中,
参与运算的操作数和结果必须在-231~231-1之间。如果需要进行更大范围的十进制整数加法,需要使用特殊的方式实现,比如使用字符串保存操作数和结果,采取逐位运算的方式。如下:
9876543210 + 1234567890 = ?
让字符串 num1="9876543210",字符串 num2="1234567890",结果保存在字符串 result = "11111111100"。
-9876543210 + (-1234567890) = ?
让字符串 num1="-9876543210",字符串 num2="-1234567890",结果保存在字符串 result = "-11111111100"。
要求编程实现上述高精度的十进制加法。
要求实现函数:
void add (const char *num1, const char *num2, char *result)
【输入】num1:字符串形式操作数1,如果操作数为负,则num1[0]为符号位'-'
num2:字符串形式操作数2,如果操作数为负,则num2[0]为符号位'-'
【输出】result:保存加法计算结果字符串,如果结果为负,则result[0]为符号位。
注:
I、 当输入为正数时,'+'不会出现在输入字符串中;当输入为负数时,'-'会出现在输入字符串中,且一定在输入字符串最左边位置;
II、 输入字符串所有位均代表有效数字,即不存在由'0'开始的输入字符串,比如"0012", "-0012"不会出现;
III、 要求输出字符串所有位均为有效数字,结果为正或0时'+'不出现在输出字符串,结果为负时输出字符串最左边位置为'-'。
示例
输入:num1 = "580"
num2 = "-50"
输出:result = "530"
输入:num1 = "580"
num2 = "-600"
输出:result = "-20"
程序代码(C语言):
#include <stdio.h>
#include <string.h>
/*判断字符串整数是否合法,合法返回'1',否则返回'0'*/
int isLegalNum(const char * num)
{
const char * num_p=num;
int num_len;//记录整数长度(不包含符号位和结束符'\0')
/*字符串指针为空,不是合法的整数,返回'0'*/
if(num_p==NULL)
return 0;
if(*num_p=='-')
num_p++;
num_len=strlen(num);
/*不合法整数,返回'0'*/
if(*num_p<=48||*num_p>57)
return 0;
int i;
for(i=0;i<num_len;i++)
{
/*不合法整数,返回'0'*/
if(*num_p>57||*num_p<48)
return 0;
}
return 1;
}
/*将字符串逆序*/
void reverseStr(char * result)
{
int i;
char temp;
int res_len=strlen(result);
for(i=0;i<res_len/2;i++)
{
temp=result[i];
result[i]=result[res_len-i-1];
result[res_len-i-1]=temp;
}
}
/*加法函数,用于将两个字符串形式的整数相加,结果保存在 char * result 中*/
void add (const char * num1, const char * num2, char * result)
{
/*判断两个字符串整数 num1 和 num2 是否合法,如果不合法则要求用户重新输入*/
if(!(isLegalNum(num1)&&isLegalNum(num2)))
{
strcpy(result,"对不起,您输入的字符串整数不是合法的十进制整数,请您检查
后重新输入,谢谢合作!");
return;
}
int count=0;//记录进位或借位
const char * num1_p;//记录第一个数的字符串起始地址
const char * num2_p;//记录第二个数的字符串起始地址
char * res_p=result;//记录结果字符串起始地址
int num1_len=strlen(num1);//第一个数的长度
int num2_len=strlen(num2);//第二个数的长度
num1_p=num1+num1_len-1;//num1_p指向第一个数的最后一位
num2_p=num2+num2_len-1;//num2_p指向第二个数的最后一位
/*加法运算,此时两个数的符号相同*/
if((*num1!='-'&&*num2!='-')||(*num1=='-'&&*num2=='-'))
{
/*两个负数相加*/
if(*num1=='-'&&*num2=='-')
{
num1_len--;
num2_len--;
int i;
for(i=0;i<(num2_len>num1_len?num1_len:num2_len);i++)
{
*res_p++=(*num1_p-'0'+*num2_p-'0'+count)%10+'0';
count=(*num1_p-'0'+*num2_p-'0'+count)/10;
num1_p--;
num2_p--;
}
/*如果第一个数的长度大于第二个数*/
if(num1_len>num2_len)
{
for(i=0;i<num1_len-num2_len;i++)
{
*res_p++=(*num1_p-'0'+count)%10+'0';
count=(*num1_p-'0'+count)/10;
num1_p--;
}
}
/*如果第一个数的长度小于第二个数*/
else if(num1_len<num2_len)
{
for(i=0;i<num2_len-num1_len;i++)
{
*res_p++=(*num2_p-'0'+count)%10+'0';
count=(*num2_p-'0'+count)/10;
num2_p--;
}
}
/*向最高位进一位*/
if(count==1)
*res_p++='1';
*res_p++='-';
*res_p='\0';
reverseStr(result);
}
/*两个正数相加*/
if(*num1!='-'&&*num2!='-')
{
int i;
for(i=0;i<(num2_len>num1_len?num1_len:num2_len);i++)
{
*res_p++=(*num1_p-'0'+*num2_p-'0'+count)%10+'0';
count=(*num1_p-'0'+*num2_p-'0'+count)/10;
num1_p--;
num2_p--;
}
/*如果第一个数的长度大于第二个数*/
if(num1_len>num2_len)
{
for(i=0;i<num1_len-num2_len;i++)
{
*res_p++=(*num1_p-'0'+count)%10+'0';
count=(*num1_p-'0'+count)/10;
num1_p--;
}
}
/*如果第一个数的长度小于第二个数*/
else if(num1_len<num2_len)
{
for(i=0;i<num2_len-num1_len;i++)
{
*res_p++=(*num2_p-'0'+count)%10+'0';
count=(*num2_p-'0'+count)/10;
num2_p--;
}
}
/*向最高位进一位*/
if(count==1)
*res_p++='1';
*res_p='\0';
reverseStr(result);
}
}
/*减法运算,此时两个数的符号不同*/
else
{
int temp=1;//记录num1和num2哪一个是负数,默认认为num1为负数
/*num1为负数*/
if(*num1=='-')
{
num1++;
num1_len--;
}
/*num2为负数*/
else
{
temp=2;
num2++;
num2_len--;
}
/*num1绝对值大*/
if(num1_len>num2_len||num1_len==num2_len&&strcmp(num1,num2)>0)
{
int i;
for(i=0;i<num2_len;i++)
{
/*不借位*/
if(*num1_p-count>=*num2_p)
{
*res_p++=(*num1_p-*num2_p-count)%10+'0';
count=0;
}
/*借位*/
else if(*num1_p-count<*num2_p)
{
*res_p++=(*num1_p+10-*num2_p-count)%10+'0';
count=1;
}
num1_p--;
num2_p--;
}
for(i=0;i<num1_len-num2_len;i++)
{
/*不借位*/
if(*num1_p-'0'-count>=0)
{
*res_p++=(*num1_p-'0'-count)%10+'0';
count=0;
}
/*借位*/
else if(*num1_p-'0'-count<0)
{
*res_p++=(*num1_p+10-'0'-count)%10+'0';
count=1;
}
num1_p--;
}
do
{
res_p--;
}
while(*res_p=='0');
/*num1是负数且绝对值大,所以此时结果为负数*/
if(temp==1)
{
res_p++;
*res_p++='-';
*res_p='\0';
reverseStr(result);
}
/*num1是正数且绝对值大,所以此时结果为正数*/
else if(temp==2)
{
res_p++;
*res_p='\0';
reverseStr(result);
}
}
/*num2绝对值大*/
else if(num1_len<num2_len||num1_len==num2_len&&strcmp(num1,num2)<0)
{
int i;
for(i=0;i<num1_len;i++)
{
/*不借位*/
if(*num2_p-count>=*num1_p)
{
*res_p++=(*num2_p-*num1_p-count)%10+'0';
count=0;
}
/*借位*/
else if(*num2_p-count<*num1_p)
{
*res_p++=(*num2_p+10-*num1_p-count)%10+'0';
count=1;
}
num1_p--;
num2_p--;
}
for(i=0;i<num2_len-num1_len;i++)
{
/*不借位*/
if(*num2_p-'0'-count>=0)
{
*res_p++=(*num2_p-'0'-count)%10+'0';
count=0;
}
/*借位*/
else if(*num2_p-'0'-count<0)
{
*res_p++=(*num2_p+10-'0'-count)%10+'0';
count=1;
}
num2_p--;
}
do
{
res_p--;
}
while(*res_p=='0');
/*num1是负数且绝对值小,所以此时结果为正数*/
if(temp==1)
{
res_p++;
*res_p='\0';
reverseStr(result);
}
/*num1是正数且绝对值小,所以此时结果为负数*/
else if(temp==2)
{
res_p++;
*res_p++='-';
*res_p='\0';
reverseStr(result);
}
}
/*num1和num2绝对值相等且异号,所以结果为'0'*/
else
{
*res_p++='0';
*res_p='\0';
}
}
}
void main()
{
char result[100];//保存结果的字符串
char num1[100];
char num2[100];
printf("请输入两个整数(整数之间用空格作为间隔符):");
scanf("%s %s",num1,num2);
add(num1,num2,result);
printf("The result is:");
printf("%s\n",result);
}
27.文件中有一组整数,要求排序后输出到另一个文件中
#include<iostream>
#include<fstream>
using namespace std;
void Order(vector<int>& data) //bubble sort
{
int count = data.size() ;
int tag = false ; // 设置是否需要继续冒泡的标志位
for ( int i = 0 ; i < count ; i++)
{
for ( int j = 0 ; j < count - i - 1 ; j++)
{
if ( data[j] > data[j+1])
{
tag = true ;
int temp = data[j] ;
data[j] = data[j+1] ;
data[j+1] = temp ;
}
}
if ( !tag )
break ;
}
}
void main( void )
{
vector<int>data;
ifstream in("c:\\data.txt");
if ( !in)
{
cout<<"file error!";
exit(1);
}
int temp;
while (!in.eof())
{
in>>temp;
data.push_back(temp);
}
in.close(); //关闭输入文件流
Order(data);
ofstream out("c:\\result.txt");
if ( !out)
{
cout<<"file error!";
exit(1);
}
for ( i = 0 ; i < data.size() ; i++)
out<<data[i]<<" ";
out.close(); //关闭输出文件流
}
链表题:一个链表的结点结构
struct Node
{
int data ;
Node *next ;
};
typedef struct Node Node ;
28. 已知链表的头结点head,写一个函数把这个链表逆序.
Node * ReverseList(Node *head) //链表逆序
{
if ( head == NULL || head->next == NULL )
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ; // 冒泡 ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
29. 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,
即便大小相同)
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
30. 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法
进行。
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}