期末复习 | CUMT高级语言程序设计

期末考试题型

  • 完善程序 20空 每个空两昏.
    阅读程序根据程序补充完整
    .内容:循环,排序算法,有面向对象

  • 程序阅读,填答案,五题,每题6昏
    比较残酷,输出结果
    面向过程,面向对象都有
    一维数组二维数组sizeof含义

  • 编程题,2题,每题15昏
    一道面向对象,一道面向过程.
    给题目,给输入输出样例.
    编程实现.
    难度不大.
    主要看面向对象的编程题

  • 综合题,给文字说明,根据文字说明具体要求实现题目要求。
    (多态继承派生)
    难度不大,时间紧张

问题提示:

  • 无switch case
  • 无运算符重载
  • 多态A卷没有,B卷有
  • 最后一次实验有相似题
  • cpp实验12月2日 难度低于作业
  • 一题面向对象,一题面向过程
  • 面向对象:字符串,二维数组
  • 面向过程:ok

知识复习

排序

  1. 冒泡排序

8188bd32183977c22632e97e2419444c

#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. 选择排序

1.将整个记录序列划分为有序区和无序区,初始时有序区为空,无序区含有待排序的所有记录 2. 在无序区选择关键码最小的记录,将其与无序区中的第一个元,使得有序区扩展一个记录,同时无序区减少了一个记录 3. 不断重复步骤 2,直到无序区只剩下一个记录为止
uTools_1676257586678

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也是运算符.

  1. 一维数组

#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;
}
  1. 二维数组

牢记: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. 数组指针和指针数组的区别

数组指针的语法为:
数据类型 (*指针变量名)[数组长度];

指针变量名+1,
对应地址移动【sizeof(数据类型)*数组长度】个字节

指针数组的语法为:
数据类型 *指针变量名[数组长度];

指针变量名+1,
对应地址移动4个字节(一个指针变量的大小)

uTools_1676284590831

字符串函数

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]

指针

指针作为函数参数与引用的区别

uTools_1676284692300

C++中继承,派生与多态

继承

语法:class 继承类名:继承方式1 基类名1 ,继承方式2 基类名2

继承关系不允许循环,在派生中,不允许类A派生出类B,类B又派生出类C,而类C又派生出类A。

20210226174353828

一个派生类继承了所有的基类方法,但下列情况除外:基类的构造函数、析构函数和拷贝构造函数。基类的重载运算符。基类的友元函数。

例:单继承的构造与析构

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的函数

顺序判断

uTools_1676285474683

静态成员

uTools_1676285654570

文件流

头文件选啥

一般写这个就行

#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()
posted @ 2023-02-13 19:05  C₅H₁₂O₄季戊四醇  阅读(210)  评论(0)    收藏  举报