《程序设计实习》课程(C++ProgrammingPractice)C++程序设计第一讲课程简介与简单程序设计2为什么要加强程序设计能力?Highthoughtsmusthavehighlanguage.——Aristophane(Greek,Comicdramatist)450BC-388BC3为什么要加强程序设计能力?Programming之于计算机专业学生Gun之于士兵为什么要加强程序设计能力?北大计算机专业学生未来可能人生规划国内就业机会=不好=好出国深造的积极性出国留学在国内读博士=高=差个人IT能力开IT公司/核心人才在家吃父母=强=差个人研究能力=强顺利毕业高级研究员拿不到学位=差结论:必须具有较高的程序设计能力!!4典型案例RickRashid博士微软公司主管研究的高级副总裁美国国家工程院院士、CMU教授、Mach操作系统项目的负责人、参与开发最早的计算机网络游戏之一AltoTrek据称,每年亲自编写近1.5万行代码!经典语录编程:艺术与科学RickRashid5内容提要6课程相关信息C语言知识巩固和补充代码风格摸底测验课程相关信息7课程内容授课方式成绩评定教材进度安排课程网页课程内容81.掌握VC++编程环境能够使用该环境进行基于控制台输入输出及文件输入输出的C及C++程序的源代码编辑、编译连接、调试和运行2.巩固和增强程序设计和代码实现能力高精度计算,日期的处理,字符串的处理,链表的概念、实现和应用,枚举和递归的求解方法。3.学习用C++语言编程基本概念(类、对象、数据抽象、重载、继承、虚函数、多态等)及其语法实现。C++程序基本构成、输入输出流及文件处理、模板、字符串处理、文件处理及标准模板库等。授课方式9课上讲授、练习及测验复习、自学和书面作业上机实习并完成上机作业期中及期末考试成绩评定10期中考试:15%上机考试期末考试:50%有B卷,考试内容为作业作业:25%平时成绩与B卷成绩加权课堂表现:10%鼓励上课主动发言随机抽取发言人将在课程网站上公布发言名单教材11自编讲义程序设计部分:《程序设计导引及在线实践》李文新等编著清华大学出版社2007C++部分:《C++大学教程》(第二版)HarveyM.Deitel,PaulJamesDeitel著邱仲潘等译冯平审校电子工业出版社2004参考教材《C++大学教程》(第五版)《C++Primer中文版》(第4版)StanleyB.Lippman,JoseeLajoie,BarbaraE.Moo著,李师贤、蒋爱军、梅晓勇、林瑛等译进度安排(暂定)122月18日第一周2月25日第二周3月03日第三周3月10日第四周3月17日第五周3月24日第六周3月31日第七周4月07日第八周课程简介与简单程序设计日期处理与高精度计算字符串处理指针和链表枚举和搜索递归和动态规划递归和动态规划类和对象进度安排(暂定)134月14日第九周4月21日第十周4月28日第十一周5月05日第十二周5月12日第十三周5月19日第十四周5月26日第十五周6月02日第十六周类和对象继承和多态String类与字符串流处理文件处理标准模板库(一)标准模板库(二)标准模板库(三)标准模板库(四)单周的课程内容根据情况由任课教师安排课程网页14北京大学信息科学技术学院网络与信息系统研究所人工智能研究室北京大学数字媒体研究所内容提要15课程相关信息C语言知识巩固和补充代码风格摸底测验C语言知识巩固和补充16位运算函数指针指针和动态内存分配命令行参数C语言标准库函数位运算17有时我们需要对某个整数类型变量中的某一位(bit)进行操作,比如,判断某一位是否为1,或只改变其中某一位,而保持其他位都不变。C/C++语言提供了“位运算”的操作,能够做到类似的操作。C/C++语言提供了六种位运算符来进行位运算操作:&按位与|按位或^按位异或~取反左移右移按位与18按位与运算符“&”是双目运算符功能:将参与运算的两操作数各对应的二进制位进行与操作,只有对应的两个二进位均为1时,结果的对应二进制位才为1,否则为0。按位与19例如:表达式“21&18”的计算结果是16(即二进制数10000),因为:21用二进制表示就是:0000000000000000000000000001010118用二进制表示就是:00000000000000000000000000010010二者按位与所得结果是:00000000000000000000000000010000按位与20按位与运算通常用来将某变量中的某些位清0或保留某些位不变。例如,如果需要将int型变量n的低8位全置成0,而其余位不变,则可以执行:n=n&0xffffff00;也可以写成:n&=0xffffff00;如果n是short类型的,则只需执行:n&=0xff00;如何判断一个int型变量n的第7位(从右往左,从0开始数)是否是1?只需看表达式“n&0x80”的值是否等于0x80即可。按位或21按位或运算符“|”是双目运算符。功能:将参与运算的两操作数各对应的二进制位进行或操作,只有对应的两个二进位都为0时,结果的对应二进制位才是0,否则为1。例如:表达式“21|18”的值是23(即二进制数10111)。按位或运算通常用来将某变量中的某些位置1或保留某些位不变。例如,如果需要将int型变量n的低8位全置成1,而其余位不变,则可以执行:n|=0xff;按位异或22按位异或运算符“^”是双目运算符。功能:将参与运算的两操作数各对应的二进制位进行异或操作,即只有对应的两个二进位不相同时,结果的对应二进制位才是1,否则为0。例如:表达式“21^18”的值是7(即二进制数111)。异或运算的特点如果a^b=c,那么就有c^b=a以及c^a=b。此规律可以用来进行最简单的加密和解密。按位非23按位非运算符“~”是单目运算符。其功能是将操作数中的二进制位0变成1,1变成0。例如,表达式“~21”的值是无符号整型数0xffffffea,而下面的语句:printf(%d,%u,%x,~21,~21,~21);输出结果就是:-22,4294967274,ffffffea左移运算符24左移运算符“”是双目运算符。其功能是将左操作数的各二进位全部左移若干位后得到的值,右操作数指明了要左移的位数。左移时,高位丢弃,左边低位补0。左移运算符不会改变左操作数的值。左移运算符25例如,常数9有32位,其二进制表示是:00000000000000000000000000001001因此,表达式“94”的值,就是将上面的二进制数左移4位,得:00000000000000000000000010010000即为十进制的144。实际上,左移1位,就等于是乘以2,左移n位,就等于是乘以2n。而左移操作比乘法操作快得多。特别注意:有符号数的左移溢出情况。#includestdio.hmain(){intn1=15;shortn2=15;unsignedshortn3=15;unsignedcharc=15;n1=15;n2=15;n3=15;c=6;printf(n1=%x,n2=%d,n3=%d,c=%x,c4=%d,n1,n2,n3,c,c4);}上面程序的输出结果是:n1=78000,n2=-32768,n3=32768,c=c0,c4=3072右移运算符27右移运算符“”是双目运算符。其计算结果是把“”的左操作数的各二进位全部右移若干位后得到的值,要移动的位数就是“”的右操作数。移出最右边的位就被丢弃。对于有符号数,如long,int,short,char类型变量,在右移时,符号位(即最高位)将一起移动,并且大多数C/C++编译器规定,如果原符号位为1,则右移时右边高位就补充1,原符号位为0,则右移时高位就补充0。右移运算符28对于无符号数,如unsignedlong,unsignedint,unsignedshort,unsignedchar类型的变量,则右移时,高位总是补0。右移运算符不会改变左操作数的值。实际上,右移n位,就相当于左操作数除以2n,并且将结果往小里取整。#includestdio.hmain(){intn1=15;shortn2=-15;unsignedshortn3=0xffe0;unsignedcharc=15;n1=n12;n2=3;n3=4;c=3;printf(n1=%x,n2=%d,n3=%x,c=%x,n1,n2,n3,c);}上面的程序输出结果是:n1=3,n2=-2,n3=ffe,c=1思考题30有两个int型的变量a和n(0=n=31),要求写一个表达式,使该表达式的值和a的第n位相同。答案:(a&(1n))n函数指针31程序运行期间,每个函数都会占用一段连续的内存空间。函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”。函数指针32函数指针定义的一般形式为:类型名(*指针变量名)(参数类型1,参数类型2,…);“类型名”表示被指函数的返回值的类型。“(参数类型1,参数类型2,……)”中则依次列出了被指函数的所有参数的类型。例如:int(*pf)(int,char);表示pf是一个函数指针,它所指向的函数,返回值类型应是int,该函数应有两个参数,第一个是int类型,第二个是char类型。函数指针33可以用一个原型匹配的函数的名字给一个函数指针赋值。要通过函数指针调用它所指向的函数,写法为:函数指针名(实参表);下面的程序说明了函数指针的用法#includestdio.hvoidPrintMin(inta,intb){if(ab)printf(%d,a);elseprintf(%d,b);}intmain(){void(*pf)(int,int);intx=4,y=5;pf=PrintMin;pf(x,y);return0;}上面的程序输出结果是:4函数指针应用:快速排序库函数qsort35voidqsort(void*base,intnelem,unsignedintwidth,int(*pfCompare)(constvoid*,constvoid*));base是待排序数组的起始地址,nelem是待排序数组的元素个数,width是待排序数组的每个元素的大小(以字节为单位),最后一个参数pfCompare是一个函数指针,它指向一个“比较函数”。快速排序库函数qsort36排序就是一个不断比较并交换位置的过程。qsort如何在连元素的类型是什么都不知道的情况下,比较两个元素并判断哪个应该在前呢?答案是,qsort函数在执行期间,会通过pfCompare指针调用一个“比较函数”,用以判断两个元素哪个更应该排在前面。这个“比较函数”不是C/C++的库函数,而是由使用qsort的程序员编写的。在调用qsort时,将“比较函数”的名字作为实参传递给pfCompare。程序员当然清楚该按什么规则决定哪个元素应该在前,哪个元素应该在后,这个规则就体现在“比较函数”中。快速排序库函数qsort37qsort函数的用法规定,“比较函数”的原型应是:int函数名(constvoid*elem1,constvoid*elem2);该函数的两个参数,elem1和elem2,指向待比较的两个元素。也就是说,*elem1和*elem2就是待比较的两个元素。该函数必须具有以下行