1 (VC++)辅导资料 一、VC++基础知识 (一)VC++的基本概念 1、程序的结构。 2、程序的执行 (1)过程 输入源程序(.cpp)→编译目标文件(.obj)→连接/构件可执行文件(.exe)。 (2)调试中的问题 1)输出信息及其含义 Compiling... t.cpp E: \test\t.cpp(7) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data t.obj - 0 error(s), 1 warning(s) 2)警告(warning) ①对运行结果无影响:float n=3.5;n=sqrt(n); ②导致运行出错:char *p; cin>>p; 3)主要错误的含义(error) ①没有定义(undeclared identifier); ②没有结尾(unexpected end of file found); ③没有返回值的函数返回某个值('void' function returning a value); ④有返回值的函数没有返回某个值(function must return a value); ⑤参数类型错误(cannot convert parameter 1 from 'int ** ' to 'int *')实参:int **,形参: int *; ⑥参数个数错误(function does not take 1 parameters); ⑦无返回值函数的调用结果参与运算等操作(illegal operand of type 'void'); ⑧输出无返回值函数的调用结果(binary '<<' : no operator defined which takes a right-hand operand of type 'void' (or there is no acceptable conversion))。 3)改错的技巧 ①找到错误所在行; ②每改一处后立即编译。 (3)执行中的问题 1)死循环 ①永无止尽的输入; ②永无止尽的输出; ③黑屏。 2)非法操作,内存使用错误 ①输出无关信息(烫); ②报“非法操作”; ③出现下列类似窗口。 2 (4)关闭 1)关闭运行窗口:Press any key to continue; 2)关闭程序:“关闭工作区”。 3、常量表示法 (1)数值 1)整数; 2)实数; 3)小数形式; 4)指数形式 ①格式:实数 E(e)整数,如 1.2e3,.4E-5; ②E(e)前的实数不能少; ③E(e)为整数。 (2)字符 1)字符与整数 ASCII 值: ①十进制 0~255; ②八进制 0~377; ③十六进制 0~FF。 2)基本表示法:‘字符’,如‘a’,‘1’。 3)转义序列表示法 ①八进制 ASCII 表示; ②十六进制 ASCII 表示; ③特殊字符表示。 (3)字符串 1)字符串的表示法:“字符串”,如“abc123”,“a”。 2)字符串与字符的区别。 3)字符串的结束标志。 3 4)字符串中特殊字符的表示 ①常见特殊字符:“、换行符、制表符、退格符等; ②表示方法:转义序列。 4、基本类型变量的说明和初始化。 5、运算符与表达式 (1)、运算符的种类 1)算术运算符 ① / ② % ③赋值运算符; ④复合赋值运算符。 2)关系运算符 ①运算结果; ②与数学中的区别:ac+d,a+b 与 c+d 进行关系运算; 2)结合性:a?b:c?d:e,a 成立时为 b,否则为 c?d:e; 3)目数。 (3)类型转换 1)自动类型转换:char→int→float→double; 2)强制类型转换:(类型)变量 或 类型(变量)。 (4)表达式 1)组成; 2)赋值; 3)逻辑表达式的优化; 4)逗号表达式 a=b+c,d,e+f。 (二)VC++的基本语句 1、顺序结构 (1)表达式语句; (2)空语句; (3)复合语句; (4)输入语句; (5)输出语句。 1)指定数制 ①仅对整数有效; 4 ②一但指定一直有效,直到重新指定; ③默认为为十进制; ④数制的转换。 int a,b,c; float x; char m; cin>>a>>oct>>b>>c>>x>>m; //123 45 67 80 .90 cout<>x>>y>>a>>b>>c>>d>>e; //输入 2.3 4.5 „a‟ „b‟ „c‟ x、y、a、b、c、d、e 的值分别是 2、0.3、4、.、5、‘、a 2、选择结构 (1)单条件语句 1)格式:if(条件)S; 2)执行过程; 3)空语句作 S 语句; 4)复合语句作 S 语句; 5)条件语句作 S 语句(嵌套)。 (2)双条件语句 1)格式:if(条件)S1;else S2; 2)执行过程; 3)else 配对。 (3)switch 语句 1)格式: switch(条件表达式) { case 常量表达式 1:语句组 1;break; case 常量表达式 2:语句组 2;break; … case 常量表达式 n:语句组 n;break; default:语句组; } 2)执行过程; 3)注意问题: ①条件表达式:变量或常量、整型或字符型; ②常量表达式:常量、整型或字符型; ③break 的作用; ④可以没有 default 。 3、循环结构 (1)for 语句 1)格式:for(表达式 1;表达式 2;表达式 3)S; 2)执行过程; 3)循环体 S: ①空语句; 5 ②循环语句(嵌套); 4)循环过程中变量值的变化; 5)注意问题: ①表达式皆可省略; ②表达式省略时,值为 1; ③防止死循环:每次循环要修改表达式 2 的值或使用 break 语句。 (2)while 语句 1)格式:while(表达式)S; 2)执行过程。 (3)do…while 语句 1)格式:do S while(表达式); 2)执行过程。 (4)break 和 continue 语句 1)break 可用于循环语句和开关语句; 2)break 中止整个循环,continue 中止本次个循环; 3)continue 只对循环语句起作用。 (三)构造类型和指针类型数据 1、构造类型数据(数组、结构体) (1)说明及初始化 1)一维数组 ①说明格式:数据类型 数组名[元素个数]; ②注意问题:元素个数为一个大于零的整型/字符型常量/常量表达式;元素下标由 0 开 始,最大下标是:数组元素个数减 1。 ③初始化:定义的同时给元素赋初值。 i)以集合的形式给出所有元素的值。int a[5]={5, 4, 3, 2, 1}; ii)以集合的形式给出部分元素的值,其余元素的值则分别被赋 0。char s[5]={„a‟ , „b‟ , „c‟ } ; iii)初始值不能多于元素的个数; iv)定义时不指定元素个数,由给出的初值个数确定数组的大小。例如:int a[ ]={1, 2, 3} ; v)全局类型或静态类型的数组,各元素有缺省的初值 0; Vi)字符数组的初始化 普通数组的方法:char s1[ ]={'a','b','c','d','e','f','g'}; char s2[20]={97,98,99,100,101,102,103}; 用字符串初始化:char s3[20]=”abcdefg”; char s4[]={ “abcdefg” }; 2)二维数组 ①说明格式:数据类型 数组名[行数][ 列数]; ②二维数组可以看成是一种特殊的一维数组。 ③初始化 i)以数组的行为单位,列出每一行的所有或部分元素;int a[3][4] = { {1, 2}, {3, 4, 5, 6}} ; ii)按顺序,给出全部或部分元素的值;int a[3][4] = { 1, 2, 3, 4, 5, 6} ; iii)给定列数,由初始化数据来确定数组的行数;int a[ ][4]={ {1, 2}, {2, 3}} ; int b[][4] = { 1, 2, 3, 4, 5, 6} ; 3)结构体:参照类 6 (2) 变量的使用 1)原则:数组的使用面向元素;结构体变量的使用除赋值(不使用动态空间)外面向 成员。 2)一维数组的使用:循环语句遍历。求和 3)二维数组的使用:二层嵌套的循环语句遍历。求对角线元素的和; 4)字符数组的使用:可整体输入、输出和用字符串处理函数 strcpy、strcmp、strcat 等; 5)结构体变量的使用:成员运算符“·”; 6)数组作函数的参数:地址传递 ①一维数组作参数:排序——交换 i)定义(形参):只需指明参数是什么类型的数组,可以不指定数组元的大小,增加一 个参数来传递数组元素的个数; ii)调用(实参):只需将数组名(数组元素的首地址/一级指针)传给函数。 ②二维数组作参数:排名——查找 i)定义(形参):必须明确数组每一行的元素个数(列数),增加一个参数来传递数组的 行数; ii)调用(实参):只需将数组名(数组元素的首地址/二级指针)传给函数。 2、指针与引用 (1)基本概念 1)变量:内存单元的名称; 2)变量的值:内存单元中的内容; 3)地址:内存单元的编号; 4)指针:内存单元的开始地址,也称指针的值,通常是一个十六进制整数; 5)指针变量:存放指针的值(变量地址)的变量(整型); 6)指针所指的值:指针所指的内存中的内容(变量的值)。 (2)指针变量的定义和初始化定义:类型 *指针变量名; 1)初始化 ①取变量的地址赋值; ②同类型的指针变量赋值。 (3)取地址运算符(&)和取值运算符(*)。 (4)指针的运算: 1)赋值运算:除初始化方法外,还可把 0 赋给指针变量; 2)算术运算:加、减,通常用于数组,表示向后、前移动存储单元/元素; 3)关系运算:判断两个指针的先后次序(存储单元的前后位置),回文字符。 (5)指针与数组 数组名就代表了整个数组的首地址,是一个地址常量,可赋值给指针变量。 1) 一维数组与指针:用指针来代替同类型的数组名。 int a[5] ={ 0 , 1 , 2 , 3 , 4 , 5 } , *p ; p=a ;则 p[i] 即为*(p+i)、a[i]、*(a+i)。 2) 二维数组与指针 二维数组的数组名是一个行地址,而不是元素地址。int a[4][5] ; a[i]表示数组 a 的第 i 行元素,相当于 a+i,a[i]是行指针,即第 i 行元素(一维数组) 的数组名。a[i][j]可表示为*(a[i]+j)。将第 i 行的行指针转化为第 i 行的元素的指针:*(a+i), 它等价于二维数组第 i 行的一维数组的数组名。因此,元素数组 a[i][j]可表示为(*(a+i))[ j ] 或 *(*(a+i)+j )。 3) 指向一维数组的指针(行指针) 7 ①定义:数据类型 (*指针变量名)[N]; ②使用:可代替同类型、数组大小与二维数组列数相等的二维数组名。 int a[4][5] ,(*p)[5 ] ; p=a ;则 a[i][j]、*(a[i]+j)、(*(a+i))[ j ] 、 *(*(a+i)+j )、p[i][j]、 *(p[i]+j)、(*(p+i))[ j ] 、 *(*(p+i)+j )都表示第 i 行第 j 列的元素。 4) 字符串与指针 字符型指针:存放字符串首地址。 使用 ①将字符串数组的首地址(数组名)赋给字符指针变量; ②将字符串赋给字符指针; ③通过键盘输入字符串给字符指针,此时字符指针不能悬空。如; char s[]="asdfg",*s1, *s2 , *s4, *s3=”C++ Program ! “; s2 =”This is a string !” ; s4=s; //s4= &s[0]; s4=s+2; cin>>s1 ; // 警告性错误 s1=s2 ; cin>>s1 ; //长度不能超过原有 s2 的长度。 (6)指针与结构体 1)结构体类型的指针; 2)指向结构体类型的变量; 3)指向结构体类型变量中的成员。 #include struct node{ char num[20] ; float score ; node *next ; }; void main() { node t={"0540305101",85.5},*p; p=&t; cout<num< void swap1(int *p1 , int *p2) { int t ; t=*p1 ; *p1=*p2 ; *p2=t ; } void swap2(int *p1 , *p2) { int *t ; t=p1 ; p1=p2 ; p2=t ; 8 } void main( ) { int a=5 , b=6 ; cout< char *backward( char *str) { char *p1 , *p2 , t ; p1=p2=str ; while(*p2++) ; // 使 p2 指向串尾 p2-= 2 ; while(p1next= NULL,NULL 的值为 0; ⑥前趋(驱)结点(p1):当前结点(p)的前一个结点。p1 ->next=p; ⑦后继结点(p2):当前结点(p)的后一个结点。p ->next=p2、p1 ->next->next=p2。 2)链表的建立 3)链表节点的插入 生成一个新的结点(当前结点 p),找到要插入的位置,然后打开原有的链表,将插入点 前一个结点作为前驱结点(p1->next=p),后一个结点作为后继结点(p->next=p2)。 4)链表节点的删除 先查找要删除的结点(p2), (结点下移:p1=p2、p2=p2->next,保持 p1 是 p2 的前驱结点); 将前驱结点(p1)的 next 指向当前结点(p2)的后一个结点(p1->next=p2->next);释放被删除结点 的动态内存 (delete p2)。 5)链表的输出和释放 10 产生链表,结点数据结构为 struct node{ int x;node *next;};且各结点的 x 值均不相同,链首指 针为 h。用函数 Del_add 对该链表操作后输出,Del_add 的功能是:若在链表上找到 x 值为 value 的结点,则删除该结点;否则构造一个新结点,其 x 值为 value,并将该结点插入链尾。 该函数要返回新链表的首指针。请完善填空。 #include struct NODE{ int x;NODE *next;}; NODE *Create() //产生一条链表 { NODE *p1,*p2,*h; h= ; //A int a; cin>>a; while(a!=-1){ p1=new NODE; p1->x=a; if(h==0){ h=p1;p2=p1;} else{ p2->next=p1;p2=p1;} cin>>a; } p2->next= ; //B return h; } void print(NODE *h) //输出链表 { const NODE *p; p=h; while(p!=0){ cout<x<<'\t'; p= ; //C } cout<x==value){ flag=1; if(p1==h){ h= ; //D delete p1; } else{p2->next= ; //E delete p1;} } else{p2=p1; p1= ; //F } } if(flag==0){ 11 p1=new NODE; p1->x=value; p1->next=0; if(h==0)h=p1; else ; //G } return h; } void main() { NODE *h; h=Create(); print(h); int value; cin>>value; h=Del_add(h, value); print(h); } 答案:A: 0 B:0 C:p->next D:h->next 或 p1->next E:p1->next F:p1->next G:p2->next=p1 (四)、函数 1、 函数的定义及调用 (1)定义格式: 类型 函数名 (参数 1,参数 2,„„参数 n) { 功能语句序列 } (2)定义时注意问题: 1)返回值类型; 2)参数; 3)return; 4)不能嵌套。 (3)调用格式为: 函数名 (参数 1,参数 2,„„参数 n) (4)调用时注意问题: 1)函数名不要加返回值类型; 2)参数前不要加参数类型; 3)参数的个数和类型应该一致; int m,a[5],b[4][5], *p, **pp;char ch,s[10],*ptr; 形 参 实 参 说 明 一般变量(int n,char c) 一般变量名(m,ch) 值传递 一般数组(int bb[][5],char ss[]) 一般数组名(b,s) 地址传递 一级指针 (int *p1, int *p2,char*p3) 一般变量的地址、元素地址 (&m,&b[2][3],&s[1]) 对指针本身 (指针)是值 传递,对指针 所指的内存 空间(值)是 地址传递 一级指针(int *p1,char*p2) 一维数组名、一级指针名(a, ptr) 指向一维数组的指针/行指针 (int(*p1)[5]) 二维数组名(b) *指针数组(intr *p1[10]) 二级指针(pp),指针变量的地址(&p), 指针数组名等 *二级指针(int **p1) 二 级 指 针名(pp), 指针变 量 的 地址 (&p),指针数组名等 引用(int &r) 一般变量名(m) 引用传递 12 前面有“*”的只需了解。 4)无值型函数与有值型函数调用时的差异。 2、 return 语句和函数返回值 (1)return 用于结束函数的运行; (2)return 应与函数返回值一致; 1) void 型函数中的 return 后面不能有值; 2) 非 void 型函数中的 return 后面一定有值,可以是常量、变量或表达式。 3、 参数的三种传递方式:值传递、地址传递、引用传递 4、 递归函数的定义及调用 (1)递归:在函数中调用自身(直接递归)或在两函数间交替调用(间接递归)。 (2)递归函数的定义 1)判断递归结束条件,如果满足,则返回确定值。 2)如果不满足递归结束条件,则根据递归公式调用函数本身(变化参数)。 通常用:if (递归结束条件) return 确定值; else return 递归公式(以变化后的参数调用函数本身); 实现,其中: ①else 通常可以省略; ②函数为 void 型时,递归公式前不能有 return。 (3)递归过程 1)递归; 2)回推。 (4)例 1)[程序] #include void fun(int *p,int i) { cout< int f(int i,int j=0) { if(j<10&&j%2)return j*i; if(j<10&&!(j%2))return j+i; if(j%2)i*=j%10; else i+=j%10; return f(i,j/10); 13 } void main(void) { int m=1,n=0; cout< int i =1; // 全局变量 1,文件作用域 void main ( ) { int i=2,k=4 ; // 外层块局部变量 14 { int i=3; // 内层块局部变量 cout << i<<’\t’< void f (void) { static int i=0;int k=0; i+=2;k+ =2; cout <<“i=”<; (3)尖括号:缺省(约定)目录,统头文件;双引号:先当前目录,再缺省目录,用 户自定义文件。 (六)、对象与类 1、 对象和类的基本概念 (1)类是对事物的抽象描述,包含数据和处理数据的函数;——数据类型 (2)对象是类的实例。——变量 (3)类的定义 1)格式 class <类名> { public: <成员数据或成员函数说明>; private: <成员数据或成员函数说明>; protected: <成员数据或成员函数说明>; }; 2)注意问题 不能指定成员数据的存储类型(static 除外)和对其初始化。 3)在类体外定义成员函数 ①先在类体内进行函数原型说明; ②再在类体外定义,格式为: <类型><类名>:: <函数名>(<参数表>) {„} //函数体 2、 数据成员和成员函数 (1) 区分有、私有和保护成员 1)public(公有)成员:访问没有限制; 2)private(私有)成员:类体内使用; 3)protected(保护)成员:类体内和派生类内使用。 (2) 成员函数的重载 类中的成员函数除析构函数外,可以重载,也可以带缺省参数。 (3) this 指针的概念 系统自动提供并隐含使用的指向正在被引用的对象本身的指针。 3、 类的构造函数和析构函数 (1) 构造函数的概念及作用 1)由系统自动调用的成员函数; 2)函数名与类相同; 3)没有返回值类型; 4)实现对象成员数据的初始化; 5)产生对象必须调用构造函数。 (2) 析构函数的概念及作用 1)撤消对象时系统自动调用的成员函数; 2)函数名固定:类名前加一个符号“~”; 16 3)没有参数,也没有返回值类型; 4)唯一性,不允许重载。 5)含有指针成员(构造函数中分配动态空间)时,必须在析构函数中释放。 (3) 类型转换构造函数和拷贝构造函数及其应用 1) 对象初始化的方法 ①用列表对公有成员初始化; ②使用一般的构造函数(c1); ③同类型的对象赋值(c2,拷贝构造函数); ④通过构造函数将列表强制转化为对象,再进行赋值(c3,先调用一般的构造函数 产生临时对象,再调用拷贝构造函数产生 c3); ⑤当构造函数只有一个参数或只有一个参数没有初值时,可以直接用单个的数据进 行初始化(c4,一般的构造函数)。 2) 下例中调用了几次构造函数?5 次。 #include class C{ int a, b; public: C(int x, int y=60) { a=x; b=y; } }; void main( ) { C c1(20,30); C c2=c1; C c3=C(50,100) ; C c4=40; } 3) 拷贝构造函数 自动生成,隐含使用,成员逐个赋值(不能含指针成员)。 C:: C(C &t) { *this=t; } 4、 类与结构体的异同 唯一区别:结构体成员的缺省访问特性是公有的,而类的缺省访问特性是私有的。 5、 派生类及其应用 (1) 继承和派生类的概念 1)继承:在原有的类(基类、父类)的基础上生成新的类(派生类、子类)的过程。 2)派生类:从基类继承来的类,可以包含父类的全部或部分(虚基类)成员,也可 以增加新的成员。 3)派生格式: class <派生类名> : <继承方式><基类名 1>, <继承方式><基类名 2>, „ { <派生类新定义成员> }; (2) 初始化基类成员、对象成员的方法 1)格式 17 类名(参数表 0):基类 1(参数表 1),基类 2(参数表 2),对象 3(参数表 3),„ { …} //新增成员的初始化 2)注意问题 ①派生成员(从基类继承过来的成员)的初始化:通过派生类的构造函数调用基类 的构造函数来完成;——通过基类名调用 ②对象成员的初始化:通过调用成员对象的构造函数来完成;——通过对象名调用 ③参数表 0 中的参数为形参,其它参数表为实参。 3)构造函数和析构函数的调用顺序 构造函数的调用顺序是先基类,再对象,最后为派生类;若有多个基类(对象),顺 序由派生(说明)的顺序决定,与派生类构造函数中基类(对象)构造函数的调用顺序无关。 析构函数的调用顺序与构造函数的调用顺序正好相反。 4)下列程序构造函数和析构函数的调用顺序是什么? #include class A{ int a ; public : A(int x) { a=x ; cout<<"调用了 A 的构造函数\n" ; } ~A( ) { cout<<"调用了 A 的析构函数 !!!\n" ; } } ; class B{ int b ; public : B(int x) { b=x ; cout<<"调用了 B 的构造函数\n" ; } ~B( ) { cout<<"调用了 B 的析构函数 !!!\n" ; } } ; class C{ int c ; public : C(int x) { c=x ; cout<<"调用了 C 的构造函数\n" ; } ~C( ) { cout<<"调用了 C 的析构函数 !!!\n" ; } } ; class D : public A, public B { // 派生的顺序 int d ; C c1 ; A a1; public : D(int x, int y, int z, int m) : B (x), A (y),a1(z), c1(m) // 构造函数调用顺序 { d=m ; cout<<"调用了 D 的构造函数\n" ; } ~D( ) { cout<<"调用了 D 的析构函数 !!!\n" ; } } ; void main( ) { D d1(1, 2, 3, 4) ; } 调用顺序: 18 调用了 A 的构造函数 调用了 B 的构造函数 调用了 C 的构造函数 调用了 A 的构造函数 调用了 D 的构造函数 调用了 D 的析构函数 !!! 调用了 A 的析构函数 !!! 调用了 C 的析构函数 !!! 调用了 B 的析构函数 !!! 调用了 A 的析构函数 !!! (3) 支配规则和赋值兼容性 (4) 虚基类的应用 6、 虚函数的概念及其应用 7、 运算符的重载及其应用 (1) 用成员函数重载运算符的方法 (2) 用友元函数重载运算符的方法 (3) 能重载的运算符有:++、--、+、-、*、/、=、+=、-=、*=、/=、<<(插入运算 符)、>>(提取运算符) 二、VC++常见错误及改正 (一)、语法错误 1、语法错误的特点 在编译时,语法错误会在“输出” 窗口中显示;双击“输出” 窗口中的“错误”,光 标就会停留在“工作区”中该错误所在的行,同时有一“箭头”指向该行。 2、语法错误的种类及改正 ★(1)、“头文件”错误 主要表现有两点: 1) 程序中使用了“库函数”而没有相应的“头文件”; 2)“库函数”和“头文件”不一致。如程序中使用了“abort()”,而没有“”, 或“头文件”不是“”。此时,显示的错误在“库函数”行(没有定义该函数)而 不在“头文件”处,改正方法是添加或修改相应的“头文件”。 ★(2)、宏定义错误 显示的错误在宏使用处(B 行),而不在宏定义处(A 行)。 如:#define PAI 3.14159; //A flaot r=2; cout<<”圆的面积为:”< class A{ int n; void print(){cout<I)continue;} k+=n; } for 中“I!=0”的值永远为真,应改为“I>0”或“I!=-1”; while 中的“continue”改 为“break”。 又如求 1+2+3+4+5+6+7+8+9+10 for(int I=1,s=0;;I++){ if(I=11)break;s+=I;} 第一次循环时,就把 11 赋给 I,此时 if 的条件为真,退出循环,s 的值为 0。 (2)、变量初始化错误 1) 变量初始化错误的表现 进行“+=”、“*=”等操作的变量,操作前通常要初始化,否则运算结果出现异 常,一般为一个非常大的负数。 ★2)变量初始化错误的改正方法 ①进行“+=” 操作的变量,一般使其初始化为 0; ②进行“*=” 操作的变量,一般使其初始化为 1。 3)如求 1~10 的和与积: int I,s,j; //应改为 int I,s=0,j=1; for(I=1;I<=10;I++) { s+=I; j*=I;} (3)、变量操作错误 变量操作错误主要表现在当程序中出现同名变量时,分不清其作用域,未合理地使 用作用域运算符。如从键盘输入 k 个正实数,求其平均值(当输入的数为 0 时结束): int k; //用于统计输入数的个数 void main() { float s=0,k; // s 为输入数的和,k 输入的数 while(1) { cin>>k; if(k= =0)break; s+=k; k++; // A 每加一个数,输入数的个数加 1 } cout<<"ave="<
还剩22页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

mhy

贡献于2013-10-30

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!