C++实训
每个
IDE
的工程文件不一样
好习惯
判空再释放
1
2
3
4
5if( NULL != rest ){
free(rest);
rest = NULL;//可以避免重复置空(free)带来的报错
}
day_01
数据类型
part1
sizeof()
是操作符,不是函数
b[40]数据类型到底是什么???
1
2
3
4
5
6
7int b[10];//10*4 = 40 字节 数据类型是什么?
/*
* b数组名:代表数组首元素的地址
* b+1: 加一个数组元素
* &b: 对数组名取地址,代表的是整个数组的地址。这个数组的数据类型是?有10个int元素的数组。
* &b+1:加一个数组
*/数据类型的本质
- 固定内存大小的别名
变量的本质
- 一段连续内存空间的别名
part2
void*
是无类型指针可以接收任何数值
在数据的封装方面用处很大
void*作为左值(放在赋值符号的左边),能“接收”任意类型的支持指针
void* 作为右值
int* p = NULL; char* p2 = (char*)malloc(sizeof(char) * 20);//malloc返回void*,所以要(char*)强制类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15* 不存在 `void`类型的变量
### part3
* 数据类型取别名
* `typedef 原来的名字 你要改的名字`
* `eg.`: `typedef unsigned int u32`
* `eg.`定于10个int元素的数据类型
* `int [10]`—>`typedef int xxx [10]`(xxx是你定义的名字)
* ```c++
//在c++中直接给数组取别名
int(&你起的名字)[3] = b;
part4
- 内存
程序生成的二级制文件分为两个部分——每次数据不同,但代码相同,所以分开
代码区
数据区
全局区与静态区
- 全局区
extern int a = 5
extern
可以不写
- 静态区
- `static int a = 5
- 常量区
- 尽量不要修改字符串常量
string
是可读不可写
- 全局区
比如查看2.2这个文件
1
2* text表示代码段的大小
* 数据区大小 = data(已经初始化数据)+bss(未初始化数据)
分区模型
重要模型
void allocSpace(char **p) { char *temp = (char*)malloc(sizeof(char)*100); if(NULL == temp){ return; } memset(tem, 0, 100); strcpy(temp, "hello world!"); *p = temp; } int main { char *p = NULL; allocSpace(&p); printf("p = %s\n", p); if(NULL != p){ free(p); p = NULL; } }
* 小巧思 * ```c++ char buf[1024] = { 0 }; //存入int100000 int a = 100000; memcpy(buf + 1, &a, sizeof(int));//三个参数:目的地,源地址,拷的字节大小 //从buf把100000输出 char* p2 = buf; printf("%d\n", *((int*)(p2 + 1)));//指向目的地,类型转换为int*(即4个字节),解引用。天才!!!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
### part5
* 栈的生长方向
* 有向上和向下两种
* 画图,内存是由低地址到高地址分配。
* 大端模式与小端模式
* 大端模式:高字节存储在低地址
* 小端模式:低字节存储在低地址(高位字节指向低位字节)
# day_02
## 指针和指针变量
* 指针是一种数据类型
* 具有固定大小的数据类型
* 指针变量是一种变量
* 一段连续内存的别名
* 不允许向 `NULL`或非法地址拷贝内存
### 野指针
* 什么情况下会导致野指针
* 指针变量没有初始化
* 指针指向的内存释放了,但指针没有置空
* 越界访问
* `char str[3] = "abc";`越界了,3要变成4.
### 指针的特性
1. 指针的步长
* 指针的步长取决于指针所指向的数据类型。
* 不同的数据类型在内存中占用不同数量的字节,因此指针在移动时会按照相应的步长进行跳跃。
```c++
char* p = NULL;
printf("%d\n", p);//0
printf("%d\n", p+1);//1
int* q = NULL;
printf("%d\n", q);//0
printf("%d\n", q + 1);//4
char buf[1024] = { 0 };
printf("%d\n", buf);//-19334423
printf("%d\n", buf+1);//-19334422
printf("%d\n", &buf);//-19334423
printf("%d\n", &buf+1);//-19334423+10241
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
722. 指针输入输出特性
* 数组为函数传入参数时:会退化为指针
* 所以在函数内部是算不出来数组的长度的
* 要在外部算好后传入进来
* 示例
* ```c++
/*
* char *p = "abcd12312ab34523abcda98367abced37abcd2qq"
* 求字符串中“abcd”出现的次数:
* 1、请自定义函数接口,完成上面需求。(50分)
* 2、自定义业务函数和main函数,设计测试用例进行测试(50分)
*/
//返回值 函数名 (参数列表)
/*
* 功能:求子串在母串中出现的次数
* author:zw
* time:
* 返回值:0:表示成功执行正常退出,-1:输入参数为空,1:
* 参数:char* str:指向母串的指针,输入参数。
char* substr:指向子串的指针,输入参数.
int* count:求子串在母串中出现的次数,输出参数
*/
int getSubCount(char* str/*in*/, char* substr/*in*/, int* count/*out*/);//一般在.h的头文件中
int getSubCount(char* str/*in*/, char* substr/*in*/, int* count/*out*/)//一般放在源文件,.c .cpp
{
//参数有效性验证
if (NULL == str || NULL == substr || NULL == count)
{
return -1;
}
//子串匹配
char* p = str;
char* sub = substr;
int m_count = 0;
while (*p != '\0')
{
p = strstr(p, sub);
if (p != NULL)
{
m_count++;
p = p + strlen(sub);
}
else
{
break;
}
}
*count = m_count;
return 0;
}
int main()
{
char* str = "abcd12312ab34523abcda98367abced37abcd2qq";
char* substr = "abcd";
int count = 0;
int result = getSubCount(str, substr, &count);
if (result != 0)
{
printf("error:func getSubCount error code %d", result);
return;
}
printf("count: %d\n", count);
return 0;
}
数组指针和指针数组
数组指针
是一个指针
定义方法一:
int(*ppArr)[3] = &arr;
定义方法二:
1
2
3int arr[3] = { 1,2,3 };
typedef int ARR_TYPE[3];
ARR_TYPE* pArr = &arr;
指针数组
是一个数组(元素为指针的数组)
栈区指针数组
char* ptr[]
表示字符指针数组。char** ptr
在函数参数中,数组退化为指针,所以二者等效
堆区指针数组
数组本身要有空间,指向的指针也要有空间
char* *p = (char **)malloc(sizeof(char*) * len);
ptr[i] = (char*)malloc(sizeof(char) * 100);
//释放资源 for (int i = 0; i < len; i++) { if (ptr[i] != NULL) { free(ptr[i]); ptr[i] = NULL; } } if (ptr != NULL) { free(ptr); ptr = NULL; }
1
2
3
4
5
6
7
8
9
10
11
123. 设计出具有自我结束能力的指针数组
```c++
void test11(){
char* ptr1[] = { "aaa","bbb","ccc",0 };
char* ptr2[] = { "aaa","bbb","ccc",NULL };
char* ptr3[] = { "aaa","bbb","ccc","\0"};
for (int i = 0; ptr1[i] != NULL; i++)
{
printf("%s\n", ptr1[i]);
}
}
函数指针和指针函数
函数是一种数据类型。将函数这种数据类型定义出来,然后定义指针。
函数指针
🌸 函数指针应用场景:做函数参数——回调函数
一个函数在编译的时候,会分配一个入口地址。这个地址就是函数的指针。函数名代表函数的入口地址。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17int add(int a, int b)
{
return a + b;
}
//1.先定义函数类型,然后通过类型定义指针
typedef int (FUNC_TYPE) (int, int)
FUNC_TYPE* myadd = add;
int result = myadd(10, 30);
//2.直接定义函数指针类型
typedef int(* FUNC_pTYPE)(int, int);
FUNC_pTYPE f = add;
int result = f(10, 30);
//3.直接定义函数指针变量
int(*func)(int, int) = add;
int result = func(10, 50);//func是指针,代表函数的入口地址。
result = (*func)(100, 200);//*func是函数名字,函数名代表函数的入口地址。函数指针数组
是个数组,其中每个元素是函数指针。
重要模型
🔴eg
: 统一接口
void printAllArray(void* arr *in*/, int len /*in*/, int elemSize /*in*/, print_type print)
void*
表示任意参数可传入print_type print
- 之前定义了
typedef void(*print_type)(void*);
函数指针当参数回调 - 对于不同数据类型的打印参数额外定义,如
void printInt(void* data)
- 之前定义了
Day_03
单链表
把节点放到结构体内,更加符合统一性和拓展性需求。
异常处理
throw
catch
1
2
3
4
5try{
}
catch{
}
智能指针
第三方库有很多
模板
泛型编程 数据类型参数化
template <typename T> void myswap(T &a, T &b) { T t; t = a; a = b; b = t; } //这样用 //myswap<int>(a, b);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36* 标准模板库 `STL`: 容器 算法 仿函数(函数对象,谓词),迭代器,适配器
* `vector`
* `iterator`
* `map`
* 函数对象: 类重载函数调用(),这个类的对象称为函数对象(仿函数)
* ```c++
template<typename T>
class ShowElement
{
public:
ShowElement()
{
mCount = 0;
}
void operator()(T elem)
{
mCount++;
cout << elem << " ";
}
void printCount()
{
cout << mCount << endl;
}
private:
int mCount;
};
void test04()
{
int a = 100;
ShowElement<int> showElement;
showElement(a); //showElement.operator()(100)
cout << endl;
}
Day_04
Qt
- Title: C++实训
- Author: Jexi Jiang
- Created at : 2024-01-15 13:43:26
- Updated at : 2024-01-18 22:03:12
- Link: https://milefer7.github.io/Jaxi-Jiang-Blog/2024/01/15/C++实训/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments