学习小知识(待更)

学习小知识

文章目录

1. Linux 命令
cd 切换工作目录
ls 查看目标文件夹中的文件内容
	-a 所有内容,包括隐藏文件和文件夹
	-l 列表形式展示,可以看到文件或者文件夹的权限内容,最后修改时间,所属权.. 
    -al 
    	权限内容	rwxrwxr-x
    			   拥有者 可读可写可执行
    			   同组人 可读可写可执行
    			   访客 可读不可写可执行
mkdir 创建文件夹
touch 创建普通文件
cp 拷贝复制文件或者文件夹
	如果是文件夹需要使用命令行参数 -r 
mv 移动/重命名目标文件过着文件夹
	文件夹操作
		mv a c ---> c 文件夹不存在,是将 a 文件夹重命名为 c 
		mv a b ---> b 文件夹存在,是将 a 文件夹移动到 b 文件夹中
rm 删除文件/或者文件夹操作
	删除操作【慎用】
	如果是文件夹,rm 操作需要使用 -rf 命令行参数
pwd 展示当前工作目录绝对路径
ifconfig 查看当前设备网络情况
cat 查看文件内容
tac 倒叙查看文件内容
nl 带有行号查看文件内容
tar -cvf 压缩
		tar -cvf test.tar 1.txt 2.txt
	-xvf 解压缩
		tar -xvf test.tar
		tar -xvf test.tar -c 指定路径
ping 测试目前网络到达其他主机的数据情况
sudo 开启超级权限,需要使用密码
chmod 
	修改文件或者文件夹权限
	r = 4
    w = 2 
    x = 1
    sudo chmod 775 1.txt ==> rwxrwxr-x
    sudo chmod 775 1.txt ==> rwxr-xr-x
2. Vim
三种模式
	编辑模式,插入元素,命令模式
	
	编辑模式 == i or o ==> 转换到插入模式
	编辑模式 == shift + : ==> 命令模式
	任意模式回到编辑模式都是 ESC
	
	编辑模式对应的常用命令
		yy yny dd dnd ngg gg p u
	命令模式常用的命令组合
		w ==> 保存
		wq ==> 保存退出
		q! ==> 不考虑保存情况,强制退出
		q ==> 退出
		wa ==> 保存 vim 打开的所有文件
		wqa ==> 保存退出 vim 打开的所有文件
		vsplit 文件名 ==> 在vim 中并列打开多个文件	
3. 基本数据类型有哪些,占用内存空间大小是多少?
整型:
	short 2 字节
	int 4 字节(32 位机及其以上)
	long 8 字节(64 位机及其以上)
浮点型:
	float 4 字节
	double 8 字节
字符型:
	char 1 字节
布尔型:
	bool 1 字节(C 语言中没有)
	补充两个关键字 true(1) false(0)
4. 变量定义的格式和要求
数据类型 变量名 = 初始化数据;

要求:
	1. 一行有且只能定义一个变量,并且在必要的情况下提供对应的注释
	2. 变量在没有进行赋值的情况下,不得参与除赋值之前的其他操作
	3. 建议变量定义之后直接进行必要的合理的初始化操作
	4. 变量先定义后使用,未定义不得使用
	5. 变量定义在一定范围内不得重复
	6. 【数据类型一致化】
5. 变量定义的常见错误
1. 未定义直接使用
	a. 变量确实未定义
	b. 拼写错误
2. 变量野值问题
	变量在没有进行赋值操作之前,不可以参与除赋值之外的其他操作,避免野值问题
3. 变量重复定义
	在用一个区域内不允许出现同名变量
4. 使用建议
	a. 给予 float 类型变量赋值,使用的常量建议末尾加上大写 F 明确告知编译器当前常量为 float 类型
	b. 给予 long 类型变量赋值,使用的常量建议末尾加上大写 L 明确告知编译器当前常量为 long 类型
	【严格遵守类型一致化要求】
6. 分支结构有哪些
1. if () 
   {}
   
2. if () 
   {} 
   else 
   {}
   
3. if () 
   {} 
   else if () 
   {} 
   else 
   {}

4. switch () 
{
    case 1:
        break;
    case 2:
        break;
        .
        .
        .
        .
    default
        break;    
}
7. 循环结构有哪些?
1. while ()
   {}

2. do
   {}
   while ();

3. for (循环条件初始化; 循环条件判断; 循环条件修改)
   { 循环体 }

break: 可以用于跳出一层循环结构或者 switch case 分支结构
continue: 结束当前次循环,直接进入下一次循环,推荐和 for 循环配合使用

for 循环结构图里分析流程

在这里插入图片描述

8. 数组定义的格式
  1. 静态类型定义
数据类型 数组名[容量] = {初始化数据};

数据类型:
	明确当前数组存储的数据类型是哪一个,有且只允许存储对应数据类型,严格遵守数据类型一致化原则。
	
数组名:
	1. 操作数组使用的必要名称
	2. 数组名存储当前数组数据在内存中的【首地址】,是一个指针变量

[容量]:
	确定当前数组的容量关系,允许最多存储多少个元素,并且一旦容量确定无法修改
	
{初始化数据}:
	针对当前数组数据类型要求,提供满足数据类型限制的初始化数据内容。
  1. 动态类型定义
数据类型 数组名 = new 数据类型[容量];
数据类型 * 数组名 = malloc/calloc 申请连续内存空 间存储目标数据类型。
9. 数组有效下表范围
数组有效下标是 0 ~ 数组容量 - 1

int arr[10]
	例如以上数组有效下表范围是 0 ~ 9
10. 尾插法添加数据方式概述
在有效元素末尾添加下一个元素
定义一个 int 类型变量 count/size,初始化为 0
	1. 添加数据元素 首先放入到下标为 count/size 对应的位置
	2. count / size += 1 操作
	
	count/size
		记录当前添加的有效元素个数
		每一次存储数据的下标位置
11. 数组作为函数参数有哪些要求
C/C++ 语言要求,数组作为函数的参数必须提供两个数据
	1. 数组本身,实际上是数组的空间首地址
	2. 数组对应容量,限制函数中操作数组范围
12. 自增自减运算符语法要求
++
--
	自增自减运算符有且只允许操作变量,不可以操作常量
	自增自减运算符在变量之前,首先执行自增自减操作,之后提供数据参与当前代码执行
	自增自减运算符在变量之后,首先取值变量数据参与当前代码行执行,之后执行变量自增自减操作
13. 运算符有哪些?
算术运算符	
	+ - * / % () =
增强版算术运算符
	+= -= *= /= %=
自增自减运算符
	++ -- 推荐使用 += 1 和 -= 1 替代
关系运算符
	> < >= <= != ==
	if (true == single) 
	{
	
	}
逻辑运算符
	&& 同真为真,有假【即】假 
	|| 有真【即】真,同假为假
	! 取反
位运算符
	计算:
		&11,有 00 
		|11,同 00
		~ 1 ==> 0 , 0 ==> 1
		^ 相同为 0,不同为 1
	移动:
		<< 目标数据 * 2 的 N 次方
		>> 目标数据 / 2 的 N 次方
14. CPU区域可以划分为哪些区域,分别有什么特征
  • 栈区
    • 主要存储局部变量(函数内定义的变量,函数参数变量,循环分支结构变量)
    • 系统分配,系统管理,系统释放
    • 可读可写不可执行
  • 堆区
    • 主要存储一些需要占用内存空间较大的变量数据,也可以认为是程序员自行申请空间用于存储部分变量数据
    • 程序员自行分配,自行管理,自行释放,如果仅申请内存不进行释放,会导致内存泄漏
    • 可读可写不可执行
    • 申请内存方式
      • C 语言
        • 需要使用 stdlib.h 中的函数 malloc realloc calloc 申请空间
        • 释放需要通过 free 函数
      • C++
        • 申请可以采用 C 语言方式,也可以使用 new 关键字
        • 释放操作如果是通过 C 语言方式创建,需要通过 free ,如果是 new 申请,需要使用 delete
  • 数据区/常量池/常量区
    • 主要存储常量数据(字符串常量,后续 const static 修饰的数据)
    • 系统分配,系统管理,系统释放
    • 可读部分可写不可以执行
  • 函数区/方法区
    • 主要存储可执行的二进制程序内容,重点是函数
    • 系统分配,系统管理,系统释放
    • 可读不可写可执行

在这里插入图片描述

15. 内存地址是什么?
	内存地址是操作系统基于内存中最小存储数据单元字节进行的【编号】,从 0 开始到内存空间的最大值,
	以 4GB 为例,内存地址范围是 0 ~ 4 * 1024 * 1024 * 1024,通常内存地址都会采用十六进制方式来处理,4GB 是0x0 ~ 0xFFFF FFFF
	内存编号,每一个字节都是一个编号
14. NULL 是内存中的哪一个字节的地址,有什么特征?
	NULL 是内存中编号为 0 的字节,对应地址为 0x0
	收到系统保护,任何程序不得读取数据,写入数据到 NULL ,如果操作系统直接 “杀死” 程序

	计算机按照最小数据存储单位【字节】,对内存中的每一个字节进行编号,编号唯一,就是【内存地址】,为了方便管理,内存通常采用 16 进制方式展示,以 4G 内存为例,地址范围是 0x0 ~ 0xFFFF FFFF
15. &* 运算符有什么功能
& 取地址运算符
	可以获取变量在内存中的首地址
* 取值运算符
	可以通过当前指针变量存储的数据内容(地址),获取地址对应指向的内存空间中的数据内容。
14. C 语言和 C++ 申请内存的函数有哪些
  1. C 语言申请内存函数
void * malloc(size_t size); //配合 memset
		 // 根据用户提供的字节数量在内存【堆区】申请内存空间,成功返回申请内存空间的首地址,失败返回 NULL
void * calloc(int num, size_t size);
		// 根据用户要求的元素个数 count 和 每一个元素占用内存字节数 size,在内存【堆区】申请内存空间,成功返回申请内存空间的首地址,失败返回 NULL
		// 特殊功能说明 calloc 具备申请内存空间擦除数据能力
void * realloc(void * ptr, size_t size);
		// 根据用户指定的 malloc calloc realloc 申请空间首地址,和当前目标新空间字节数,调整目标内存空间,如果原地址空间足够使用,返回原地址空间,如果原地址空间后续内存无法满足当前需求,CPU 会分配新的空间,同时拷贝原数据内容,返回的是新地址。如果申请失败,返回 NULL
		// 【使用要求】返回到主函数时必须使用指针变量,存储新空间首地址
  1. C++ 申请内存函数
new 关键字
15. C 语言和 C++ 释放空间的函数有哪些
  1. C 语言释放内存函数
free(void * ptr);
		// 可以释放通过 malloc calloc realloc 申请的内容空间,要求提供对应空间首地址,当前函数所需参数为 void * 万能指针,可以提供任意类型的指针地址。
		// 释放之后建议将指针变量赋值为 NULL
  1. C++ 释放内存函数
delete 关键字
16. 一个 int 类型数组,解释一下操作分别对应什么
  • 回顾:
    1. 数组名是什么???
    数组名是一个指针常量,存储当前数组在内存中的首地址
    2. 数组名存储的地址
    1. 整个数组的首地址
    2. 同时也是数组中下标为 0 的元素首地址。

  • *arr = arr[0];
    *arr 取值操作,根据当前内存地址,以及指针数据类型,获取对应内存数据存储情况
    相当于获取数组中下标为 0 的元素

  • *arr + 5 = arr[0] + 5;

  • *(arr + 5) = arr[5]
    arr + 5 已当前 arr 地址 + 5 * 对应数据类型空间字节数
    相当于获取数组中下标为 5 的元素首地址
    *(arr + 5) ==> arr[5];

  • arr + 5 = &arr[5];
    arr + 5 已当前 arr 地址 + 5 * 对应数据类型空间字节数
    相当于获取数组中下标为 5 的元素首地址

17. 结构体定义
struct 结构体名称
{
	成员变量 【数据类型 变量名】;
	成员变量 【数据类型 变量名】;
	成员变量 【数据类型 变量名】;
}

typedef struct student
{
	int id;
	char name[32];
	int age;
}Student;
18. 结构体变量定义
Student stu;
19. 申请内存堆区空间存储结构体类型数据的方式
Student *stu = (Student *)calloc(1, sizeof(Student));
20. ->. 运算符的区别
-> 结构体指针操作对应结构体中的数据内容
	Student *stu ...
	stu->id
. 结构体变量操作其中的成员变量数据内容
	Student stu
	stu.id
21. 添加数据到数组中指定下标位置,流程概述
  1. 合法性判断
    判断用户提供的下表数据是否合法
    判断数组数据是否合法(为空)
  2. 从原本最后一个有效元素开始,到用户指定插入数据位置结束,数组中的元素整体向后移动
  3. 在指定下标位置进行数据添加操作
    【注意】如果容量不足,需要进行扩容操作,扩容操作仅针对于通过 malloc calloc realloc 申请的动态数组内存空间
22. 添加数据到链表指定下标位置,流程概述
  1. 合法性判断
    a. 用户指定的下标位置是否合法性,链表中采用的下 标也是从 0 开始。
    b. 判断链表头和结点数据是否为 NULL
  2. 判断用户提供的下标情况
    a. 用户指定下标为 0 ,【add_first】;
    b. 用户指定下标为 head->size, 【add_last】;
    c. 需要根据用户指定的下标位置进行遍历链表操作,找到目标添加位置的原本结点 index > head->size / 2 从末尾开始搜索数据,否则从链表头开始
  3.    // new_node 新结点,target 目标结点 
       new_node->next = target; 
       new_node->prev = target->prev; 
       new_node->prev->next = new_node; 
       target->prev = new_node;
       head->size += 1
    
23. 案例说明什么是二级指针

在这里插入图片描述

24. 有头链表,链表头结构体和结点结构体代码实现,以及组成内 容注释建议说明
// 结点类型 
typedef struct node 
{ 
	// 当前结点的上一个结点 
	struct node * prev; 
	// 当前结点的下一个结点 
	struct node * next; 
	// 结点中存储的数据内容,采用 void * 支持任意数据 类型。
	void * data; 
} Node; 

typedef struct head 
{ 
	// 整个链表中的第一个结点 
	Node * first; 
	// 整个链表中的最后一个结点 
	Node * last; 
	// 当前链表中的有效结点/元素个数 
	int size; 
} LinkedHead;
25. 举例函数指针案例
  • 格式:
    • 函数返回值类型 (* 函数指针名)(对应的函数形式参数数据类型列表);
      int (*pf)(int, int)
      函数名是一个指针常量,定义的函数指针名称为 pf ,可以存储相同数据类型的函数的首地址
  • 要求:
    1. 当前函数指针可以存储的函数,它的返回值类型要求为 int 类型
    2. 存储的函数,它的参数类型要求为(int, int )两个 int 类型
    3. 给予函数指针 pf 赋值的是函数名
  • 例子:计算得到两个 int 类型数据之和
    /*
    定义一个计算得到两个 int 类型数据之和的函数
    定义一个计算得到两个 int 类型数据之和的函数
    
    @param n1 用户提供的 int 类型数据
    @param n2 用户提供的 int 类型数据
    @return 两个 int 类型数据之和,返回值数据类型为 int 类型
    */
    int add(int n1, int n2);
    
    int main(int argc, char const *argv[])
    {
       /*
       pf 就是函数指针,要求
    	     1. 对应函数的返回值数据类型必须是 int 类型
          2. 对应函数的形式参数列表必须是(int, int)
      */
    	int (*pf)(int, int) = add;
       /*
       函数指针,可以直接当做对应函数使用
       */
      int ret = pf(10, 20);
      printf("ret = %d\n", ret);
    
    	 return 0;
    }
    
    int add(int n1, int n2)
    {
      return n1 + n2;
    }
    
26. 函数指针作为函数参数的案例
	int operation(int n1, int n2, int (*pf)(int, int));

	int add(int n1, int n2);
	int sub(int n1, int n2);
	int mul(int n1, int n2);
	int div(int n1, int n2);
	
	// 插件式编程
	operation(10, 20, add);
	operation(10, 20, sub);
	operation(10, 20, mul);
	operation(10, 20, div);
27. 举例说明结构体嵌套,和动态内存申请之后的操作赋值
typedef struct date 
{
    char year[8];
    char month[4];
    char day[4];
} Date;
typedef struct person 
{
   	int id;
    char name[32];
    Date hiredate; // 入职时间
} Person;

Person * p = (Person *)malloc(sizeof(Person));
memset(p, 0, sizeof(Person));

strcpy(p->hiredate.year, "2024");
strcpy(p->hiredate.month, "1");
strcpy(p->hiredate.day, "11");
28. 案例说明有参宏和无参宏
#define COUNT 10 // 无参宏
#define ADD(a, b) (a + b) // 有参宏
	
printf("count : %d\n", COUNT); ==> printf("count : %d\n", 10);
printf("add : %d\n", ADD(10, 20)); ==> printf("add : %d\n",(10 + 20));
29.<>"" 方式引入头文件的区别
<> 直接去系统指定路径搜索目标头文件
"" 在当前目录下搜索目标头文件,如果未找到前往系统指定路径搜索目标头文件
30. C++ 和 C语言结构体有什么不同
  1. C++ 结构体的数据类型名称直接就是 struct 关键字之后的名称
    C 语言结构体的名称是 struct + 结构体名
  2. C++ struct Student 结构体数据类型名称为 Student
    C struct student 数据类型名称为 struct student
  3. C++ 结构体允许定义函数/声明函数,C 语言不允许。
31. 命名空间中可以定义哪些内容,如何引入命名空间

命名空间中可以定义 变量,函数,数据类型,用于限制作用范围,避免名称冲突

例如:
	using namespace std;
	使用命名空间 std, 可以直接在代码中使用 cin cout endl 等相关内容。
32. 作用域运算符有什么用
格式:
	::
	可以用于限制函数,变量的归属
例子:
	命名空间 A 中的变量 n1 
	A :: n1
	命名空间 A 中的函数 test();
	void A::test() { ... }
33. 有头单项链表添加元素到最后一个结点的代码实现
	typedef struct node
	{
		struct node * next;
		void * data;
	} Node;
	
	typedef struct head
	{
		Node * first;
		int size;
	} LinkedHead;
	
int add_last(LinkedHead * head, Node * new_node) 
{
    if (NULL == head || NULL == new_node)
    {
        printf("提供的链表头或者结点为 NULL\n");
        return EXIT_FAILURE;
    }
    
    if (0 == head->size)
    {
        // 当前链表中没有有效结点
        head->first = new_node;
    }
    else
    {
        // 当前链表中有其他结点,利用循环,遍历整个链表,找到最后一个元素位置
        // 【标记】next ===> NULL
        Node * temp = head->first;
        while (temp->next != NULL) 
        {
            temp = temp->next;
        }
        
        temp->next = new_node;
    }
    
    head->size += 1;
    
    return EXIT_SUCCESS;
}
34. const 关键字修饰变量的特征,举例说明
const int num = 10; // num 可以认为是带有名称的常量,后续数据无法修改。

const int * p = &num; 
//p 指针存储的地址可以修改,但是指向的数据空间内容无法修改

int * const p = &num1; 
//p 指针存储地址无法修改,但是指向的数据空间内容可以修改

const int * const p = &num1; 
//p 存储地址无法修改,同时指向的数据空间内容无法修改。

35. 条件编译有哪些
#if		#else	#endif
#ifdef	#else	#endif
#ifndef	#else	#endif

#define
#undef
36. 函数有默认参数的函数形式
void test(int n1, int n2 = 10);

main() 
{
    test(10); // n1 = 10, n2 = 10;
    test(10, 200); // n1 = 10, n2 = 200
}

void test(int n1, int n2)
{
    cout << "n1 : " << n1 << ", n2 : " << n2 << endl;
}
37. 案例说明引用作为函数参数交换数据
void swap(int & r1, int & r2);
main ()
{
	int n1 = 10;
	int n2 = 20;
	
	swap(n1. n2);
	// 结果为 n1 = 20, n2 = 10;
}

void swap(int & r1, int & r2)
{
	int temp = r1;
	r1 = r2;
	r2 = temp;
}
38. C++ 中权限修饰符有哪些,分别有什么作用
public
	修饰的内容类内,类外,子类都可以使用
protected 
	修饰的内容类内,子类可以使用,类外无法使用
private 
	修饰的内容有且只能类内使用,类外,子类无法使用
39. C++ 构造函数有哪些,对应的格式和作用
例如类名为 Person
无参数构造函数
	Person() {..}
有参构造函数
	Person(int id, string name, int age) {..}
拷贝构造函数
	Person(const Person & person);
  • 构造函数的名称是类名,在和 new 关键字配合使用,提供数据类型名称,告知 new 关键字申请的内存空间字节数。
  • 构造函数用于初始化申请空间的内存
    无参数构造函数,有参数构造函数,拷贝函数
40. C++ 析构函数的格式和作用
例如类名为 Person 
析构函数格式:
	~Person() {}
  1. delete 关键字释放 new 申请内存空间,如果对应的数据为一个类,自动触发析构函数执行。
  2. 析构函数中可以将当前对象成员申请的内存或者打开的资源进行关闭操作。
41. C++ 继承的格式,以及各种权限继承的结果
class 派生类:权限修饰符 父类
{
}
父类采用的权限修饰符	public 		protected 		private
继承采用的权限修饰符
		public 		public 		protected 		无法继承
		protected 	protected 	protected		无法继承
		private		private 	private			无法继承
42. 重写和重载的区别
	重载【relaod】
		1. 在同一个范围以内,包括同一个文件,同一个命名空间,同一个类或者结构体中
		2. 要求函数名称必须一致
		3. 要求函数对应的形式参数列表必须不一致
		4. 函数返回值数据类型不作为重载的判断要求
	重写【Override】
		1. 必须存在继承关系
		2. 要求父类子类函数声明必须完全一致
		3. 函数体内容可以根据实际情况修改
43. C++ 引用&和指针*的区别
  • 引用表示当前变量的别名,可以认为是当前变量本身,在编译阶段不占用内存空间,执行时会存在临时空间使用
  • 指针是存储一块内存的空间首地址
44. 一个函数所需参数为父类,可以传入的实际参数有哪些

函数所需参数为父类类型,可以提供给函数的实际参数可以是父类本身或者其子类【多态】

45. 纯虚函数有什么要求,纯虚函数所在类是什么类

virtual void test() = 0;

  • 要求:
    1. 要求 virtual 关键字修饰
    2. 纯虚函数有且只有函数声明
    3. 要求必须使用 = 0 结尾,明确表示当前函数为纯虚函数
  • 所在类是【抽象类(abstract)】
    1. 抽象类无法进行实例化操作
    2. 子类是一个实现类,继承抽象类,要求实现所有的 纯虚函数
    3. 子类继承抽象类,完成部分纯虚函数,子类也是抽象类
46. 字符串常用函数
  • 字符串拷贝函数
  // 将 src 指向的字符串内容,拷贝到 dest 字符数据空间中
  char *strcpy(char *dest, const char *src);
   
  // 将 src 指向的字符串内容,拷贝到 dest 字符数据空间中,最多复制 n 个字符
  char *strncpy(char *dest, const char *src, size_t n);
   
  // 从 src 复制 n 个字符到 dest。
  void * memcpy(void * dest, const void *src, size_t n);
   
  // 另一个用于从 src 复制 n 个字符到 dest 的函数。
  void * memmove(void *dest, const void *src, size_t n);
   
  // 复制字符 c (一个无符号字符) 到参数 src 所指向字符串的前 n 个字符。
  void memset(void *src, int c, size_t n);
  

【注意】

  1. src 可以是字符串常量,也可以是字符数组
  2. dest 必须是可以存储字符数据的内存空间,一般是字符数组或者动态申请内存字符空间,而且要求空间足够使用
  • 字符串追加函数
  // 把 src 所指向的字符串追加到 dest 所指向的字符串结尾
  char *strcat(char *dest, const char *src);
   
  // 把 src 所指向的字符串追加到 dest 所指向的字符串结尾,直到 n 字符长度为止或者到末尾标记 '\0'
  char *strncat(char *dest, const char *src, size_t n);
  

【注意】

  1. 末尾标记’\0’
  2. 返回值数据类型为 char *,返回内容是 dest 对应的空间地址
  3. dest 必须有对应内存空间
  • 字符串比较函数
  // 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
  int strcmp(const char *str1, const char * str2);
   
  // 把 str1 和 str2 进行比较,最多比较前 n 个字节。
  int strcmp(const char *str1, const char *str2, size_t n);
  
  // 把 str1 和 str2 的前 n 个字节进行比较。
  int memcmp(const void *str1, const void *str2, size_t n);

【注意】

  1. 0 表示 str1 和 str2 两个字符串前 N 个字符一致
  2. 1 or -1 表示两个字符串前 N 个字符不一致。
  • 字符串查找指定字符函数
   // 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。
   char *strchr(const char *str, int c);
   
   // 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
   char *strrchr(const char *str, int c);
   
   // 在字符串 haystack 中查找第一次出现字符串 needle(不包含空结束字符)的位置。
   char *strstr(const char*haystack, const char *needle);
   
   // 在参数 str 所指向的字符串的前 n 个字节中搜索第一次出现字符 c(一个无符号字符)的位置。
   void *memchr(const void *str, int c, size_t n);
  
  • 计算字符串长度函数
	// 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。
	size_t strlen(const char *str);
  • 字符串分解函数
	// 分解字符串 str 为一组字符串,delim 为分隔符。
	char *strtok(char *str, const char *delim)
47. 模板函数的定义格式和模板对应具体数据类型的约束方式
  • 定义模板函数
	template <typename T>
	void test(T t) {...}
  • 当前模板函数中模板对应的具体数据类型需要通过实际参数来约束
	test(10); ===> void test<int>(int t);
	test("10"); ===> void test<string>(string t);
	test('A'); ===> void test<char>(char t);
48. 模板类定义和模板类中模板对具体数据的约束方式
  • 定义模板类
	template <typename K, typename V>
	class Data
	{
		// 成员变量,成员函数,构造函数都可以使用模板
	private:
		K key;
		V value;
	};
  • 模板类中模板对应的具体数据类,需要再实例化对象的过程中明确约束
	Data<string, int> * data = new Data<string, int>("我在废土世界扫垃圾", 89);
	// 以上代码 data 中模板 K 对应具体数据类型为 string 类型, v 对应 int 类型
 
	Data<float, double> * data = new Data<float, double>(10.5F, 10.5);
	// 以上代码 data 中模版 K 对应具体数据类型为 float 类型,v 对应 double 类型
49. 一个类继承模版类,模版对应的具体数据类型有哪些约束方式
  • 自由模式
	template <typename T>
	class Handler {...};
 
 template <typename T>
 class MyHandler : public Handler<T> {...

【注意】
MyHandler 中模版类型尚未明确并且和父类中的一致,需要在实例化对象过程中约束模版对应具体数据类型

  • 严格模式
	template <typename T>
 class Handler {...};
  
  class IntHandler : public Handler<int> {...}

【注意】
IntHandler 类中没有模版,继承父类中模版已经明确为 int 类型,对应的函数,变量使用到模版数据类型的位置都是 int 类型

50. 友元函数和友元类
class Dog;
	
	class Person 
	{
	public:
		friend void showPerson(Person & p);
		friend class Dog;
	private:
		int id;
		string name;
		int age;
	}
	
	class Dog 
	{
	// 可以在 Dog 类内操作 Person 私有化数据.
	}
	
	void showPerson(Person & p) 
	{
		cout << "ID: " << p.id 
			<< ", Name : " << p.name 
			<< ", Age : " << p.age << endl;
	}
51. 一个类继承带有纯虚函数的类有什么要求
  • 当前类是一个实现类:
    要求实现父类中的所有纯虚函数
  • 当前类还是一个抽象类:
    可以选择实现父类中的纯虚函数
52. STL 容器有哪些,底层结构分别对应
  • string 容器
    可变容量数组
  • vector 容器
    仅支持单边操作的可变长数组
  • deque 容器
    双端操作的可变长数组【链表 + 数组】
  • stack 容器
    栈, 底层是一个【单向链表】
  • queue 容器
    队列, 底层是一个【有头单向链表】
  • list 容器
    双向有头链表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值