期末复习 | CUMT高级语言程序设计
期末考试题型
-
完善程序 20空 每个空两昏.
阅读程序根据程序补充完整
.内容:循环,排序算法,有面向对象 -
程序阅读,填答案,五题,每题6昏
比较残酷,输出结果
面向过程,面向对象都有
一维数组二维数组sizeof含义 -
编程题,2题,每题15昏
一道面向对象,一道面向过程.
给题目,给输入输出样例.
编程实现.
难度不大.
主要看面向对象的编程题 -
综合题,给文字说明,根据文字说明具体要求实现题目要求。
(多态继承派生)
难度不大,时间紧张
问题提示:
- 无switch case
- 无运算符重载
- 多态A卷没有,B卷有
- 最后一次实验有相似题
- cpp实验12月2日 难度低于作业
- 一题面向对象,一题面向过程
- 面向对象:字符串,二维数组
- 面向过程:ok
知识复习
排序
- 冒泡排序

#include <stdio.h>
// perform the bubble sort
void bubbleSort(int array[], int size) {
for (int step = 0; step < size - 1; ++step) {//进行n-1次
for (int i = 0; i < size - step - 1; ++i) {//注意此处为size-step-1(考试时常用i来代替外层循环变量step,j来代替内层循环变量i)
if (array[i] > array[i + 1]) {
int temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
}
}
}
- 选择排序
1.将整个记录序列划分为有序区和无序区,初始时有序区为空,无序区含有待排序的所有记录 2. 在无序区选择关键码最小的记录,将其与无序区中的第一个元,使得有序区扩展一个记录,同时无序区减少了一个记录 3. 不断重复步骤 2,直到无序区只剩下一个记录为止
void selectSort(int a[],int n){
for(int i=0;i<n-1;i++){//进行n-1趟选择
int index=i;
for(int j=i+1;j<=n;j++)//从无序区选取最小的记录
if(a[index]>a[j])
index=j;
if(index!=i)
swap(a[i],a[index]);
}
}
一维数组二维数组sizeof含义
sizeof虽然用法很像函数,但它真的是运算符.new和delete也是运算符.
- 一维数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
//数组名是首元素的地址
//1.sizeof(数组名)-数组名表示整个数组
//2.&数组名-数组名表示整个数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); //sizeof(数组名)-计算的数组的总大小,16
printf("%d\n", sizeof(a + 0)); //数组名表示首元素的地址,a+0表示的是首元素的地址,4/8
printf("%d\n", sizeof(*a)); //*a表示的是首元素,4
printf("%d\n", sizeof(a + 1)); //a+1表示的是第二个元素的地址,4/8
printf("%d\n", sizeof(a[1])); //第二个元素的大小,4
printf("%d\n", sizeof(&a)); //&a取出的是数组的地址,数组的地址也是地址,4/8
printf("%d\n", sizeof(*&a)); //&a是数组的地址,数组的地址解引用访问的数组,16
printf("%d\n", sizeof(&a + 1)); //&a是数组的地址,&a+1虽然跳过了整个数组,但是还是地址,4/8
printf("%d\n", sizeof(&a[0])); //&a[0]是第一个元素的地址,4/8
printf("%d\n", sizeof(&a[0] + 1)); //&a[0]+1是第二个元素的地址,4/8
return 0;
}
- 二维数组
牢记:a[i] = *(a+i)
“回字有四样写法” ——孔乙己
- sizeof(a); 数组名a是单独放在sizeof中的,所以计算的数组的总大小
int main()
{
int a[3][4] = { 0 };
sizeof(a);//48
return 0;
}
- sizeof(a[0][0]);
int main(){
int a[3][4] = { 0 };
sizeof(a[0][0]);//4
return 0;
}
- sizeof(a[0]) 输出第一行大小
int main(){
int a[3][4] = { 0 };
sizeof(a[0]);//16
return 0;
}
- sizeof(a[0]+1) 输出第一行第2个元素大小
int main(){
int a[3][4] = { 0 };
sizeof(a+1);//4/8
return 0;
}
- sizeof(a+1) 二维数组第二行的地址,地址=(4/8)对比sizeof(a)
int main(){
int a[3][4] = { 0 };
sizeof(a+1);//4/8
return 0;
}
- sizeof(*(a+1)) 第二行的大小
int main(){
int a[3][4] = { 0 };
sizeof(*(a+1));//16 *(a+1)==a[1]表第二行的地址
return 0;
}
- sizeof(&a[0]+1) 第二行的地址
int main(){
int a[3][4] = { 0 };
sizeof(&a[0]+1);//4
return 0;
}
- sizeof(*(&a[0]+1))
int main(){
int a[3][4] = { 0 };
sizeof(*(&a[0]+1));//16
return 0;
}
- sizeof(*a); 类似*(a+1)
int main(){
int a[3][4] = { 0 };
sizeof(*a);//16
return 0;
}
- sizeof()内部表达式不计算
int main(){
short s=5;
int a=4;
printf("%d\n",sizeof(s=a+6));//2
printf("%d\n",s);//5
return 0;
}
- 数组指针和指针数组的区别
数组指针的语法为:
数据类型 (*指针变量名)[数组长度];
指针变量名+1,
对应地址移动【sizeof(数据类型)*数组长度】个字节
指针数组的语法为:
数据类型 *指针变量名[数组长度];
指针变量名+1,
对应地址移动4个字节(一个指针变量的大小)

字符串函数
strcpy
strcpy(s1,s2); 将s2内容拷贝到s1中
Demo:
string s1[]=“123456\0”;
string s2[]=“abc\0”;
strcpy(s1,s2);
s1[]=>”abc\056\0”;
strcmp
从左到右返回两字符串第一个不相同字母的ASCII码差,返回0值是相等,不要使用if(strcmp(s1,s2))来执行两个字符串一致时的操作
strlen
用于获取字符串的长度,不是字符数组的长度
strcat
字符串连接函数
Usage: char *strcat(char *dest, const char *src)
dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
src -- 指向要追加的字符串,该字符串不会覆盖目标字符串。
String 类
拷贝:s1 = s2
比较:s1 == s2
连接:s1 + s2
算长度:s.length()
访问第i个元素:s[i]
指针
指针作为函数参数与引用的区别

C++中继承,派生与多态
继承
语法:class 继承类名:继承方式1 基类名1 ,继承方式2 基类名2
继承关系不允许循环,在派生中,不允许类A派生出类B,类B又派生出类C,而类C又派生出类A。

一个派生类继承了所有的基类方法,但下列情况除外:基类的构造函数、析构函数和拷贝构造函数。基类的重载运算符。基类的友元函数。
例:单继承的构造与析构
class base
{
public:
base() { cout << "base构造函数" << endl; };
~base() { cout << "base析构函数" << endl; };
};
class derive : public base
{
public:
derive() { cout << "derive构造函数" << endl; };
~derive() { cout << "derive析构函数" << endl; };
};
int main()
{
derive s;
}
/*base构造函数
derive构造函数
derive析构函数
base析构函数
例2:派生类对象可作为基类的对象来使用
#include<iostream>
using namespace std;
class base
{public:
void test() { cout << "base的函数" << endl; };
};
class derive : public base
{
public:
void test() { cout << "derive的函数" << endl; };
};
int main()
{
derive s;
s.test();
s.base::test();//::为作用域
base* p = &s;
p->test();//调用base的函数
}
/*derive的函数
base的函数
base的函数*/
例3:
class a {
public:void get(){cout << "a的函数" << endl;}
};
class b : public a {
public:void get() { cout << "b的函数" << endl; }
};
class c : public b{
public:void get() { cout << "c的函数" << endl; }
};
int main()
{
a* first = new b;
a* second = new c;
first->get();//动态类型为a,静态为b
second->get();//动态类型为a,静态为c
b* third = new c;
third->get();//动态类型为b,静态为c
}
/*a的函数
a的函数
b的函数*/
例4:多继承的构造与析构
class base1
{
public:
base1() { cout << "base1构造" << endl; };
~base1() { cout << "base1析构" << endl; };
};
class base2
{
public:
base2() { cout << "base2构造" << endl; };
~base2() { cout << "base2析构" << endl; };
};
class derive :public base1, public base2
{
public:
derive() { cout << "derive构造" << endl; };
~derive() { cout << "derive析构" << endl; };
};
int main()
{
derive s;
}
/*base1构造
base2构造
derive构造
derive析构
base2析构
base1析构
例5:菱形继承(虚继承相关)
fly_horse继承horse,bird而两者都继承自animal,animal中的age变量,也会被继承下去,fly_horse类得到了两份animal类的age变量,并且是两个独立的变量。我们应该清楚,这种数据我们有一份就可以了。
class animal{public:int age;};
class hourse : public animal{};
class bird : public animal{};
class fly_hourse : public hourse, public bird{};
int main()
{
fly_hourse s;
s.hourse::age = 10;
s.bird::age = 15;
cout << s.hourse::age << endl;
cout << s.bird::age << endl;
}
// 输出10 15
利用虚继承(在继承前加virtual关键字),使得在派生类中只保留一份间接基类的成员。
class animal{public:int age;};
class horse : virtual public animal{};
class bird : virtual public animal{};
class fly_horse : public horse, public bird{};
int main()
{
fly_horse s;
s.horse::age = 10;
s.bird::age = 15;
cout << s.horse::age << endl;
cout << s.bird::age << endl;
}
// 输出15 15,两份age数据此时只有一份了,
//无论加哪个父类的作用域都只有一个值。
多态
-
静态多态 : 函数重载和运算符重载属于静态多态,复用函数名。函数地址早绑定,编译阶段确定函数地址
-
动本多态 : 派生类和虚函数实现运行时多态。函数地址晚绑定,运行阶段确定函数地址
-
多态满足的条件:有继承关系。子类重写父类中的虚函数。父类指针或引用指向子类对象
-
重写:函数返回值类型,函数名参数列表完全一致称为重写
class animal {public:virtual void speak(){}};
class dog :public animal {
public:void speak()//子类重写父类中的虚函数
{ cout << "dog的函数" << endl; }};
class cat:public animal {
public:void speak()
{ cout << "cat的函数" << endl; }};
void animal_speak(animal & a)//父类指针或引用指向子类对象
{
a.speak();//调用不同的函数
}
int main()
{
dog b;
cat c;
animal_speak(b);
animal_speak(c);
}
//dog的函数
//cat的函数
顺序判断

静态成员

文件流
头文件选啥
一般写这个就行
#include<fstream>
fstream既可以读,也可以写
ifstream仅可读文件
ofstream仅可写文件
创建文件指针对象:
ifstream fp(ADDRESS,ios::in);
ofstream fp(ADDRESS,ios::out);
一直访问直到文件末尾:while(!fp.eof()){}
while(!fp.eof()){
...
}
凡是打开了文件流,务必关闭该文件流(如果你想继续使用该对象进行文件操作,先close,再open)
fp.close()


浙公网安备 33010602011771号