c基础学习教程.pptx
《c基础学习教程.pptx》由会员分享,可在线阅读,更多相关《c基础学习教程.pptx(139页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、第一节 c+概述main()函数标准输入输出流exit语句数据类型标准库string类型引用类型指针和const限定符动态内存分配第1页/共139页1.1 main()函数intmain()return0;每个c+程序必须含有main()函数,且main函数是唯一被操作系统显式调用的函数定义函数必须制定4个元素:返回类型、函数名、形参表、函数体。操作系统通过main的返回值来确定程序是否成功执行完毕,返回0表示程序成功执行完毕,通常非0表示有错误出现第2页/共139页1.2 标准输入输出流C+没有直接定义进行输入/输出的任何语句,这个功能由标准库提供。包含两个类:输入流istream和输出流o
2、stream.#includeusingnamespacestd;标准库中的四个IO对象cin标准输入(如键盘),为istream对象cout标准输出(如显示屏),为ostream对象cerr标准错误,用于输出警告和错误信息,为ostream对象clog用于产生程序执行的一般信息,为ostream对象第3页/共139页cin读入流(由键盘输入)作用从键盘取得数据送至内存,与一起使用结合方向为自左向右例如:intv1,v2;cinv1v2;从流中读取信息时,输入流缓冲指针跟踪最后一个读入到流的字符,每次尝试从流获取信息时,都从指针的当前位置开始qcin自动跳过空白字符(whitespace)q返
3、回值为左操作数第4页/共139页用cout写入到流(输出到屏幕)cout必须与输出操作符一起使用,结合方向为自左向右例如:coutEntertwonumbersendl;coutdecx;(hex/oct)作用将右操作数插入到cout中,可同时接受不同类型的数据输出,所以可有多个操作符,把信息写入流时,把信息添加到流的末尾,相当于从左到右输出endl(endofline)为操纵符,具有换行效果,并刷新与设备相关联的缓冲区,刷新后用户可立即看到写入到流中的输出。注:忘记刷新可能会造成输出停留在缓冲区,建议在程序员调试过程中,这些语句都应刷新输出流中,setw(n):为后面的输出项预留n列第5页/
4、共139页1.3 exit()语句形式:exit(interger_value);执行exit语句时,程序立即终止。一般来说,如果因为一个错误而调用exit,就使用1,其他情况使用0。该函数在头文件cstdlib中,所有要有预编译命令#includeusingnamespacestd;第6页/共139页1.4 内置数据类型常量宏常量:#definePI3.1415926系统不为其分配内存,只是简单的字符串替换const常量:const类型常量标识符=值;常量定义后不能修改,所以必须初始化例如:constdoublePI=3.1415926;系统为PI分配内存单元两种常量的比较const常量有数
5、据类型,而宏常量没有数据类型;编译器可以对const常量进行类型合法性检查,而对宏常量仅仅是字符的替换,没有合法性检查,并且在字符替换的时候可能产生意想不到的错误c+中,const常量完全可以取代宏常量第7页/共139页q布尔类型bool,它的值只有两个true和false可以将算术类型的任何值赋给bool对象。0代表false非0代表trueq初始化:创建对象并给它赋初值(赋值指擦除对象的当前值并用新值代替)有两种形式:复制初始化:用等号intval=1024;直接初始化:初始化式放在括号中intval(1024);通常在一个对象首次使用的地方定义该对象第8页/共139页1.5 标准库str
6、ing类型#includeusingnamespacestd;string对象的定义和初始化strings2(s1);/s1为string对象或字符串字面值strings3(n,c);/s3为n个c注意:字符串字面值和标准库string类型不是同一类型string对象的读写输入:cins;/从第一个非空字符读至下一个空白字符读入一行getline(cin,line);两个参数:输入流对象和string对象功能:从输入流的中读取内容到line中,换行符是该行的结束标志注:getline()不忽略开头的换行符,但line并不保存换行符,即若开头遇换行符,line为空stringq输出:coutse
7、ndl;第9页/共139页#include#includeusingnamespacestd;intmain(intargc,char*argv)stringstr;coutInputastringstr;/输入str的时候,只要遇到了空格,就会结束输入coutstrendl;coutInputalineusinggetlineendl;getline(cin,str);coutstrstr;输入了一次回车,这个语句遇到回车就结束,这样,回车符也跟着到了内存,到用getline()再输入时,内存里第一个字符就是回车,所以getline()一读到这个回车就结束了,所以getline(cin,st
8、r);不起作用。解决:处理掉cinstr;遗留的回车符,可以在该语句下加一句:getchar();/吸收内存里的回车符第10页/共139页string对象的操作s.empty();若字符串为空,返回trues.size();返回s中字符的个数qsn;返回s中位置为n的字符qs1=s2;比较,所有的比较运算符都可以使用qs1+=s2;连接qs1=s2;赋值,string类型可以和字符串字面值连接,赋给string类型,但是,+操作符的左右操作数必须至少有一个string类型strings=hello+,+s1;第11页/共139页1.6 引用类型引用就是对象的另一个名字,主要用于函数的形参引入v
9、oidswap(inta,intb)inttemp=a;a=b;b=temp;intmain()intx=10,y=20;swap(x,y);q形参与实参有各自不同的内存空间,若实参是一个复杂对象,重新分配内存会引起程序执行效率大大下降q形参对实参为值传递,对形参的任何改变不会引起实参值的改变第12页/共139页1.6.1 非const引用引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。声明:类型标识符&引用名=目标变量名;inta;int&ra=a;/定义引用ra,它是变量a的引用(别名)(1)&在此不是求地址运算,而是起标识作用。(2)声明引用时,必须同时对其进行
10、初始化。(3)引用声明完毕后,相当于目标变量名有两个名称,不能再把该引用名作为其他变量名的别名。(4)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。第13页/共139页非const引用intival=1024;1.引用必须在定义时初始化,int&refval=ival;一旦绑定到某对象不可以将引用int&refval1;绑定到另一对象int&refval2=refval;2.不能定义引用类型的引用,int&ref1=4;必须用与该变量同类型对象初始化int&
11、ref2=ival+5;3.引用对应的值必须具有相应的内存空间,以便对这个空间进行引用。常量、表达式、引用不能赋给引用例:inti=5;intj=6;int&k=i;k=j;/k和i的值都变成了6;第14页/共139页1.6.2 const引用格式:const 类型标识符&引用名=目标变量名;用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。int a;const int&ra=a;ra=1;/错误a=1;/正确引用型参数应该在能被定义为const的情况下,尽量定义为const。第15页/共139页 对const对象的引用consti
12、ntival=1024;inti=34;constint&refval=ival;refval=512;int&ref2=ival;constint&ref3=42;constint&ref=i;constint&ref4=ref3+3;vrefval是对const型的引用,所以任何对refval的赋值都是非法vconst对象必须用const引用vconst引用可以绑定到相关的类型的对象,或绑定到右值第16页/共139页1.6.3 指针和引用的比较指针和引用都可间接访问另一个值,但是1、引用总是指向某个对象,定义时必须初始化。指针则可以在任何时候被初始化2、引用一旦被初始化,就不能改变引用的关
13、系而指针则可以随时改变所指向的对象3、赋值:引用即为别名,给引用赋值修改的是该引用所关联的对象的值(非const引用)而指针可以更改其指向的对象,也可以更改所指向的对象的值4、不能有NULL引用,引用必须与合法的存储单元关联,而指针则可以是NULL第17页/共139页1.7 指针和const限定符使用const修饰指针时,由于const的位置不同,而含意不同。1.7.1指向const对象的指针指向const的指针,不可以通过该指针修改对象,但可以其他方式修改double dval=3.14,pi=3.1415;const double*ptr=&dval;/const限定了指针所指的对象类型,
14、非ptr*ptr=;/不合法 指针所指的对象不能改 ptr=π/合法,指针值可变dval=3.1415;/合法第18页/共139页若一个指针是指向const对象,则该指针必须具有const特性。例如constdoublepi=3.14159;constdouble*ptr=π/正确double*ptr1=π/错误,const对象要用指向const的指针来指向,这样可以保证既不能通过*ptr,也不能通过pi修改其值指向const的指针常用作函数的形参,这样可以确保函数的实参在函数调用过程中不被修改voiduse_ptr(constint*p)第19页/共139页1.7.2 co
15、nst指针固定指向一个对象的指针,即指针本身是常量char*const ptr1=stringptr1;/const放在类型说明和变量之间ptr1=stringptr2;/非法,指针本身的值不可改变*ptr1=m;/合法 指针所指的变量的值可以改变若指针及指针所指向的变量的值都不可以更改constchar*constptr=stringptr;第20页/共139页1.8 动态内存分配一内存分配有三种方式n从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。n栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的
16、存储区。里面的变量通常是局部变量、函数参数等。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。1.堆,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。第21页/共139页1.8.2 单个对象的动态分配与释放动态分配:由关键字new及其后面的类型指示符构成。该类型指示符可以是内置类型或class类型。例:newint;从堆中分配了一个int型的对象。newStudent;分配了一个Student类对象。需要
17、注意的是堆中分配的对象没有名字。new表达式返回了一个指向该对象的指针,对该对象的全部操作都要通过这个指针间接完成。例如:pint*pi=newint;该new表达式创建了一个int型的对象,由pi指向它。初始化int*pi=newint(0);该语句表示pi指向一个int型的对象,该对象的初始值为0。括号中的表达式被称作初始化式第22页/共139页动态内存的释放与静态分配内存的对象不同,编译器不会自动释放它们所占的内存-除非整个程序结束。所以当动态分配内存的对象完成它的使命,需要被销毁的时候不能依赖编译器,而要靠程序员用delete释放。格式:deletepi;/释放pi所指向的内存空间指针
18、pi本身是个在全局域中声明的全局对象,它的生命期由编译器控制。pi的存储区在程序开始之前就被分配,一直保持到程序结束。而pi指向的对象的生命期是由程序员控制的,它是在程序执行过程中遇到new表达式时才被创建,遇到delete表达式时被销毁并收回存储区第23页/共139页动态内存的释放delete只能用在指向内存是用new动态分配的指针上,如果将其在指向堆以外内存的指针上,会使程序运行期间出现未定义的行为。唯一的例外是,当指针指向NULL时,不管指针指向的对象是如何分配内存的,都不会引发麻烦。voidf()inti;char*str=asdd;int*pi=&i;short*ps=NULL;do
19、uble*pd=newdouble(123.3);deletestr;/危险!str指向的不是动态对象deletepi;/危险!pi指向的对象i是一个局部对象deleteps;/安全!ps指向NULLdeletepd;/安全!pd指向一个动态分配的对象第24页/共139页常见错误1忘记了释放内存,造成内存泄露。含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存泄漏(memoryleak)。函数体内的局部变量在函数结束时自动消亡。例如p是局部的指针变量,它消亡的时候会让它所指的动态内存一起消亡。这是错觉!voidFunc(
20、void)char*p=(char*)malloc(100);/动态内存会自动释放吗?指针消亡了,并不表示它所指的内存会被自动释放2对同一内存区应用了多次delete表达式。这通常发生在多个指针指向同一个动态分配对象的时候。若多个指针指向同一对象,当通过某一个指针释放该对象时就会发生这种情况。3内存被释放了,并不表示指针会消亡或者成了NULL指针,形成野指针第25页/共139页野指针因此,当程序执行deletepi;语句时,pi指向对象的内存被释放,但指针pi本身的内存并没有受到delete表达式的影响。在deletepi;之后,pi被称作空悬指针(俗称野指针),即指向无效内存的指针。空悬指针
21、是错误的根源,它很难被检测到,如果对它进行操作将会产生无法预测的结果。一个比较好的办法是在指针所指的对象被释放后,马上将该指针设置为NULL,这样可以清楚地表明该指针不再指向任何对象char*p=(char*)malloc(100);strcpy(p,“hello”);free(p);/p所指的内存被释放,但是p所指的地址仍然不变if(p!=NULL)/没有起到防错作用strcpy(p,“world”);/出错第26页/共139页野指针指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:classApublic:voidFunc(void)cout“FuncofclassA”Fu
22、nc();/p是“野指针”第27页/共139页1.8.3 数组的动态分配与释放new表达式也可以在堆中分配数组。在这种情况下new表达式中的类型指示符后面必须有一对方括号,里面的值代表数组的长度,而且该数值可以是一个复杂的表达式。new表达式返回指向数组第一个元素的指针。动态分配数组只需指定类型和长度格式:new typesize;/size为数组元素的长度,可以是任意表达式。new返回指向新分配数组的第一个元素的指针。例如:int*p2;p2=new intn;qdelete 释放new分配的存储空间delete p;/表明p指向的是动态存储区的数组,如果遗漏,编译器无法发现错误第28页/共
23、139页int*pi=newint(1024);/分配单个int型的对象,用1024初始化int*pia=newint1024;/分配一个含有1024个元素的int型数组,未被初始化第29页/共139页第二节 函数参数传递函数返回值内联函数函数的重载第30页/共139页2.1 参数传递C+语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。在调用函数时,对于每一个实参,其类型必须与对应的形参类型相同,或可被转换为该形参类型2.1.1普通的非引用形参为传值调用,调用时将实参的值赋给形参,而形参的任何改变不会改变实参voidswap(intp1,intp2)inttemp=p1
24、;p1=p2;p2=temp;调用时:inta=5,b=9;swap(a,b);/a、b并没有互换第31页/共139页 指针形参指针传递传递的是地址,函数可以通过指针赋值,修改指针所指向的对象的值void swap(int*p1,int*p2)int temp=*p1;*p1=*p2;*p2=temp;调用时怎么写?q1、若要保护指针指向的对象的值,则形参需定义为指向const对象的指针voiduse_ptr(constint*p)在函数体中,不能通过*p修改p指向的对象的值实参既可以为int*,也可以为constint*类型第32页/共139页2、如果输入参数采用“值传递”,由于函数将自动产
25、生临时变量用于复制该参数,调用结束释放所以该参数本来就无需保护,没有必要加const修饰。例如不要将函数voidFunc1(intx)写成voidFunc1(constintx)。同理不要将函数voidFunc2(Aa)写成voidFunc2(constAa)。其中A为用户自定义的数据类型。对于非内部数据类型的参数而言,象voidFunc(Aa)这样声明的函数注定效率比较低。因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为voidFunc(A&a),因为“引用传递”仅借用一下参数的别名而已第33页/共139页2.1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基础 学习 教程
限制150内