1. calloc和realloc
void test()
{
int* p = calloc(10, sizeof(int));
for (int i = 0; i < 10; ++i)
p[i] = i + 1;
for (int i = 0; i < 10; ++i)
printf("%d ", p[i]);
if (p != NULL)
{
free(p);
p = NULL;
}
}
void test()
{
int* p = malloc(sizeof(int) * 10);
for (int i = 0; i < 10; ++i)
p[i] = i + 1;
for (int i = 0; i < 10; ++i)
printf("%d ", p[i]);
printf("\n%d\n", p);
p = realloc(p, sizeof(int) * 20);
printf("%d\n", p);
for (int i = 0; i < 10; ++i)
printf("%d ", p[i]);
if (p != NULL)
{
free(p);
p = NULL;
}
}
2. sscanf
void test()
{
//%*s或%*d 忽略数字或字母,跳过数据
char* str = "12345abcde";
char buf[1024] = { 0 };
sscanf(str, "%*d%s", buf);
printf("buf: %s\n", buf);
}
void test()
{
//%*s或%*d 忽略数字或字母,跳过数据
//忽略字符串到空格或者\t
char* str = "abcde 12345";
char buf[1024] = { 0 };
sscanf(str, "%*s%s", buf);
printf("buf: %s\n", buf);
}
void test()
{
//%[width]s 读指定宽度的数据
char* str = "12345abcde";
char buf[1024] = { 0 };
sscanf(str, "%6s", buf);
printf("buf: %s\n", buf);
}
void test()
{
//任何匹配从第一个字符开始,如果不满足条件会直接退出匹配过程
//%[a - z] 匹配a到z中任意字符
char* str = "12345abcde";
char buf[1024] = { 0 };
sscanf(str, "%*d%[a-c]", buf);//先忽略数字
printf("buf: %s\n", buf);
}
void test()
{
//%[aAb] 匹配aAb中的一员,贪婪性
char* str = "aABbcde";
char buf[1024] = { 0 };
sscanf(str, "%[aAb]", buf);
printf("buf: %s\n", buf);
}
void test()
{
//%[^a] 匹配非c的任意字符,贪婪性
char* str = "aABbcde";
char buf[1024] = { 0 };
sscanf(str, "%[^c]", buf);
printf("buf: %s\n", buf);
}
void test()
{
//%[^a-z] 表示读取除a-z以外的所有字符
char* str = "1234aABbcde";
char buf[1024] = { 0 };
sscanf(str, "%[^a-z]", buf);
printf("buf: %s\n", buf);
}
void test()
{
char* str = "abcde#12uiop@0p1";
char buf[1024] = { 0 };
sscanf(str, "%*[^#]#%[^@]", buf);
printf("buf: %s\n", buf);
}
3. 查找子串
//查找子串第一次出现的位置
char* myStr(const char* str, const char* substr)
{
const char* mystr = str;
const char* mysub = substr;
while (mystr != '\0')
{
if (*mystr != *mysub)
{
++mystr;
continue;
}
//此时已找到第一个相同的字母
const char* temp_mystr = mystr;
const char* temp_mysub = mysub;
while (*temp_mysub != '\0')
{
if (*temp_mystr != *temp_mysub)
{
++mystr;
break;
}
++temp_mysub;
++temp_mystr;
}
if (*temp_mysub == '\0')
return (char*)mystr;
}
return NULL;
}
void test()
{
char* str = "abcdefg";
char* sub = "de";
char* pos = myStr(str, sub);
printf("pos = %s\n", pos);
}
4. 指针易错点
4.1 越界
4.2 指针叠加会不断改变指针指向,所以最后无法free§
4.3 返回局部变量地址。当操作某块内存时,该内存需要是合法的(自己申请,使用的时候还没释放)
4.4 同一内存释放多次
void test()
{
char* p = NULL;
p = (char*)malloc(50);
strcpy(p, "abcdef");
if (p != NULL)
{
//free()函数的功能只是告诉系统p指向的内存可以回收了,即将p
//指向的内存使用权交还给系统,但是p的值还是原来的值(野指针),
//p还是指向原来的内存
free(p);
}
}
5. const的使用
struct Person
{
char name[64];
int age;
int ID;
double score;
};
//使用值传递,每次开辟80字节的空间,不建议
void print(struct Person p)
{
printf("Name:%s Age:%d ID:%d Score:%f\n", p.name, p.age, p.ID, p.score);
}
void test()
{
struct Person person = { "Trump",70,250,59.9 };
print(person);
}
struct Person
{
char name[64];
int age;
int ID;
double score;
};
//地址传递,每次4个字节
//如果是指针的话,代表拿到的是原始数据的内存空间,就有可能在使用过程中修改元数据的值
//为了规避地址传递的副作用,使用const
void print(const struct Person *p)
{
printf("Name:%s Age:%d ID:%d Score:%f\n", p->name, p->age, p->ID, p->score);
}
void test()
{
struct Person person = { "Trump",70,250,59.9 };
print(&person);
}
6. 指针的指针(二级指针)
6.1 输出特性
void allocateSpace(int **temp)
{
int* arr = malloc(sizeof(int) * 10);
for (int i = 0; i < 10; ++i)
{
arr[i] = i + 1;
}
//指针间接赋值
*temp = arr;
}
void print(int *arr,int len)
{
for (int i = 0; i < len; ++i)
printf("%d ", arr[i]);
}
void freeSpace(int **arr)
{
if (arr == NULL)
return;
if (*arr != NULL)
{
free(*arr);
*arr = NULL;
arr = NULL;
}
}
void test()
{
int* pArray = NULL;
allocateSpace(&pArray);//取完地址指针升级,一级指针变为二级
print(pArray, 10);
freeSpace(&pArray);
if (pArray == NULL)
{
printf("\npArray被置空!\n");
}
}
6.2 输入特性
二级指针做形参输入特性是指由主调函数分配内存
void print(int** arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", *arr[i]);
}
}
void test()
{
//堆上分配指针数组
int** pArray = malloc(sizeof(int*) * 6);
//栈上分配数据空间
int a1 = 100;
int a2 = 200;
int a3 = 300;
int a4 = 400;
int a5 = 500;
int a6 = 600;
*(pArray + 0) = &a1;
*(pArray + 1) = &a2;
*(pArray + 2) = &a3;
*(pArray + 3) = &a4;
*(pArray + 4) = &a5;
*(pArray + 5) = &a6;
print(pArray, 6);
//释放数组内存
if (pArray != NULL)
{
free(pArray);
pArray = NULL;
}
}
void print(int** arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", *arr[i]);
}
}
void test()
{
int* pArray[5];//栈上开辟指针数组
for (int i = 0; i < 5; ++i)
{
pArray[i] = malloc(4);//整形4个字节
*(pArray[i]) = 100 + i;
}
print(pArray, 5);
//释放堆内存
for (int i = 0; i < 5; ++i)
{
if (pArray[i] != NULL)
{
free(pArray[i]);
pArray[i] = NULL;
}
}
}
6.3 文件读写
void print(int** contents, int lines)
{
for (int i = 0; i < lines; i++)
{
printf("%d行:%s", i+1, contents[i]);
}
}
//释放文件数据内存
void freeFileSpace(char** contents, int lines)
{
for (int i = 0; i < lines; ++i)
{
if (contents[i] != NULL)
{
free(contents[i]);
contents[i] = NULL;
}
}
free(contents);
contents = NULL;
}
int getFIleLines(FILE* file)
{
if (NULL == file)
{
return -1;
}
char buf[1024] = { 0 };
int lines = 0;
while (fgets(buf, 1024, file) != NULL)
{
++lines;
}
//恢复文件指针,指向文件起始位置
fseek(file, 0, SEEK_SET);
return lines;
}
void read(FILE* file, int lines, char **contents)
{
if (NULL == file)
return;
if (NULL == contents)
return;
if (lines <= 0)
return;
//创建缓冲区
char buf[1024] = { 0 };
int index = 0;
while (fgets(buf, 1024, file) != NULL)
{
//printf("buf:%s", buf);
int curLineLen = strlen(buf) + 1;
//给当前行分配内存
char *lineContent = malloc(sizeof(char) * curLineLen);
//将行数据拷贝到空间中
strcpy(lineContent, buf);
contents[index++] = lineContent;
memset(buf, 0, 1024);
}
}
void test()
{
//根据文件中每行的长度开辟内存空间
//先读文件根据行数开辟指针数组
FILE* file = fopen("./test.txt", "r");
if (NULL == file)
{
printf("open error!");
return;
}
//统计文件行数
int lines = getFIleLines(file);
printf("lines:%d\n", lines);
char** pContents = malloc(sizeof(char*) * lines);//每个char *保存一行数据
//读取文件内容
read(file, lines, pContents);
//打印文件内容
print(pContents, lines);
//释放文件数据
freeFileSpace(pContents, lines);
//关闭文件
fclose(file);
file = NULL;
}
7 位逻辑运算符
7.1 按位取反
void test() {
int number = 2;//010 101负数使用补码存储:110 + 1 = 111-->-3
printf("~number : %d\n", ~number);
}
7.2 位与 &
void test() {
int number = 332;
if ((number & 1) == 0) {
printf("%d是偶数!\n",number);
}
else
printf("%d是奇数!\n", number);
number &= 0;//将number置零
}
7.3 位或 |
void test() {
int num1 = 5; int num2 = 3;
printf("num 1 | num2 = %d\n", num1 | num2);
}
7.4 位异或 ^
void test() {
int num1 = 5; int num2 = 9;//交换两个数不需要临时变量
printf("num1:%d num2:%d\n", num1, num2);
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
printf("num1:%d num2:%d\n", num1,num2);
}
8 移位运算符
8.1 左移
void test() {
//左移几位就相当于乘以2的几次方
int num = 20;
printf("number = %d\n", num << 1);
}
8.2 右移