C++补充知识汇总

一、字符数组

1、定义C语言中利用字符数组表示C++中的字符串

1
2
3
4
5
6
7
char 变量名[] = "字符串值"  (包含’\0‘)(推荐)

char 变量名1[] = {'字','符','串','值'} (不包含‘\0’)

char* 变量名2= "字符串值" (包含’\0‘)

printf("%s\n",变量名)

注意:C风格的字符串要用双引号括起来

C++风格字符串:

1
string 变量名 = "字符串值"

2、常用考题:利用sizeof和strlen计算字符数组的大小

2.1、sizeof关键字:计算一个数据类型的大小,不过sizeof不是一个函数,它是一个运算符,所以它不需要包含任何头文件

2.2、strlen函数:计算一个指定字符串的长度,函数原型是size_t strlen(const char *s),它的返回值是size_t类型,也就是unsigned int类型,返回的是字符串的长度,需要包含头文件#inlude <string.h>,参数s是字符串首地址。

2.3、区别:

2.3.1、sizeof会将空字符\0计算在内,而strlen不会将空字符\0计算在内

2.3.2、sizeof会计算到字符串最后一个空字符\0并结束。

2.3.3、而strlen如果遇到第一个空字符\0的话就会停止并计算遇到的第一个空字符\0前面的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main(void)
{
//1、
char str[100] = "abcde";
printf("sizeof(str) = %lu\n", sizeof(str)); //字节大小为100
printf("strlen(str) = %lu\n", strlen(str)); //字符串长度为5
//2、
char str1[] = "abcde";
printf("sizeof(str1) = %lu\n", sizeof(str1)); //字节大小为6
printf("strlen(str1) = %lu\n", strlen(str1)); //字符串长度为5
//3、
char str2[] = "\0abcde";
printf("sizeof(str2) = %lu\n", sizeof(str2)); //字节大小为7
printf("strlen(str2) = %lu\n", strlen(str2)); //字符串长度为0
//4、
char str3[] = "\0ab\0c de";
printf("sizeof(str3) = %lu\n", sizeof(str3)); //字节大小为9
//5、
char str6[] = "ab cde";
printf("strlen(str6) = %lu\n", strlen(str6)); //字符串长度为6

return 0;
}

二、内存对齐

1、定义:内存对齐是指实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数

1
2
3
4
5
6
7
8
9
10
11
12
//32位系统
#include<stdio.h>
struct{
int x;
char y;
}s;

int main()
{
printf("%d\n",sizeof(s); // 输出8
return 0;
}

2、内存对齐规则

2.1、基本类型的对齐值就是其sizeof值;。

2.2、结构体的对齐值是其成员的最大对齐值;

2.3、编译器可以设置一个最大对齐值,怎么类型的实际对齐值是该类型的对齐值与默认对齐值取最小值得来的。

3、实例

由对齐规则可以知道,结构体的对齐值为sizeof(i)=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
//默认Linux32位系统(#pragma pack(4):有效对齐单位为4字节)
#include<stdio.h>
struct
{
int i;
char c1;
char c2;
}x1;

struct{
char c1;
int i;
char c2;
}x2;

struct{
char c1;
char c2;
int i;
}x3;

int main()
{
printf("%d\n",sizeof(x1)); // 输出8
printf("%d\n",sizeof(x2)); // 输出12
printf("%d\n",sizeof(x3)); // 输出8
return 0;
}

4、内存对齐的意义:减少内存碎片,提高内存的访问速度

5、修改默认内存对齐数:使用预处理指令:#pragma pack(n) 进行修改

三、回调函数

1、回调函数:就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。(函数指针作为函数参数

2、实例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

//函数指针的定义
typedef int(*callback)(int,int);

//函数指针的赋值
int add(int a,int b,callback p){
return (*p)(a,b);
}
//回调函数的定义
int add(int a,int b){
return a+b;
}
int main(int argc,char *args[]){
//函数指针的调用
int res = add(4,2,add); //6
printf("%d\n",res);
return 0;
}

3、实例二

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
#include <stdio.h>
#include <string.h>

//函数指针的定义
typedef int (callBack)(const void *buffer,size_t size,char *p_out);

//函数指针的赋值
void callFunc(callBack *consume_bytes, char *p_out) {
printf("callFunc\n");
const void *buffer = NULL;
consume_bytes(buffer,0,p_out); //传入值可以随便填
}

//回调函数的定义
int callBackFunc(const void *buffer, size_t size, char *p_out){
printf("callBackFunc\n");
memset(p_out,0x00,sizeof(char)*100);
strcpy(p_out,"encoderCallback:this is string!");
return 1;
}

int main(int argc,char *args[]){
char p_out[100];
callFunc(callBackFunc,p_out); //函数指针的调用
printf("%s\n",p_out);
/*
callFunc
callBackFunc
encoderCallback:this is string!
*/
return 0;
}

四、字符串函数

1、strlen

1
size_t strlen(const char * str)
  • 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)
  • 函数的返回值为size_t,是无符号
  • 实现:求字符串长度,不包含’\0‘

2、strcpy

1
char* strcpy(char * destination,const char * source )
  • 源字符串必须以’\0‘结束
  • 实现:字符串复制

3、strcat

1
char * strcat ( char * destination,const char * source )
  • 实现:字符串追加

4、strcmp

1
int strcmp ( const char * str1,const char * str2 )
  • 实现:比较字符串内容是否相等

5、strncpy

1
char *strncpy(char *dest, const char *src, int n)
  • 更安全,有长度限制

6、strncat

1
char *strncat(char *dest,char *src,int n)

7、strncmp

1
int strncmp ( const char * str1, const char * str2, size_t n )

8、strstr

1
const char* strstr(const char* str1, const char* str2)
  • 实现:查找子串

五、内存函数

1、memcpy

1
void * memcpy ( void * destination,const void * source,size_t num )
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
  • 这个函数在遇到’\0’的时候并不会停下来
  • 实现:不重叠内容拷贝

2、memove

1
void * memmove ( void * destination,const void * source,size_t num ) 
  • 实现:重复内容拷贝

3、memset

1
void * memset ( void * ptr,int value,size_t num )
  • 实现;给内容设置

六、常用标准输入输出函数

一、scanf

1、函数实现:按用户指定的格式从键盘上把数据输入到指定的变量之中

1
int scanf(const char * restrict format,...)

2、注意事项

  • 默认使用一个或多个空格、tab 键、回车键作为数据输入的分隔符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include<stdio.h>
    int main(void)
    {
    int a,b,c;

    printf("请输入三个数字:"); // 1 2 3
    scanf("%d %d %d",&a,&b,&c);
    printf("%d,%d,%d\n",a,b,c); //1,2,3
    return 0;
    }
  • 若使用其他符号作为分隔符,那相应的输入也需要添加对应的符号

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main(void)
{
int a,b,c;

printf("请输入三个数字:");
scanf("%d, %d, %d",&a,&b,&c);
printf("%d, %d, %d\n",a,b,c);
return 0;
}

二、getcharputchar

1、函数实现:从标准输入中获取和打印一个字符

1
2
int getchar(void);
int putchar(int char)
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main()
{
char ch ;
while ((ch=getchar()) != 'EOF') //"EOF":表示读取结束
{
putchar(ch);
}
return 0;
}

三、sscanf

1、函数实现:解析字符串中的参数

1
int sscanf(const char *str, const char * format, ...);

2、测试样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
int day, year;
char weekday[20], month[20], dtm[100];

strcpy( dtm, "Saturday March 25 1989" );
sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year );

printf("%s %d, %d = %s\n", month, day, year, weekday ); //March 25, 1989 = Saturday

return(0);
}

四、sprintf

1、函数实现:将要输出的内容复制到str中

1
int sprintf(char *str, const char *format, ...)

2、测试样例

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <math.h>

int main()
{
char str[80];

sprintf(str, "Pi 的值 = %f", M_PI);
printf("%s\n", str); //Pi 的值 = 3.141593

return(0);
}

七、动态内存管理

1、malloc

1
void* malloc (size_t size)
  • 实现:向内存申请一块连续可用的空间,并返回指向这块空间的指针
  • 返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  • 为了避免内存泄漏(申请的内存空间,别人无法继续使用):一般和free函数(释放动态内存空间)联合使用

2、calloc

1
void* malloc (size_t num, size_t size)
  • 实现:申请初值全为0内存空间
  • 用free释放申请的内存空间

3、realloc

1
void*rea1loc (void* ptr, size_t size)
  • 实现:对申请的内存空间进行扩容

  • ptr是要调整的内存地址

  • size是调整之后的新大小

  • 返回值为调整之后的内存起始位置(新开辟一块内存空间,并将原来的内容拷贝过去

  • 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

  • realloc在调整内存空间是存在两种情况的:

    1、如果原有空间后面有足够的空闲空间,则直接从堆上现存的数据后面的那些字节中获得附加的字节

    2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存

  • 用free释放申请的内存空间

八、容器的迭代器失效

1、序列式容器迭代器失效

对于序列式容器,例如vector、deque;由于序列式容器是组合式容器当前元素的iterator被删除后,其后的所有元素的迭代器都会失效,这是因为vector,deque都是连续存储的一段空间,所以当对其进行erase操作时,其后的每一个元素都会向前移一个位置。

2、关联式容器迭代器失效

对于关联容器(如map, set,multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。

3、容器适配器

stack,queue,priority_queue

九、

1、