day10 coding: 动态内存申请,内存泄漏,字符串处理函数

This commit is contained in:
flykhan 2023-07-17 19:24:01 +08:00
parent 6d70975834
commit 66a7bdfe2e
24 changed files with 744 additions and 0 deletions

46
day11/d1.c Normal file
View File

@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
int *create_int_arr(int n)
{
// 申请内存空间
int *arr = (int *)malloc(n * sizeof(int));
// 条件判断时,常量放在前面,变量放在后面
if (NULL == arr)
{
// printf("malloc error\n");
perror("malloc error"); // 打印错误信息, perror 会打印出错误信息
return NULL; // 返回空指针
}
perror("malloc success"); // 打印成功信息
return arr; // 返回数组首地址
}
void input_int_data(int *q, int n)
{
int temp = n;
// 输入数据
while (n--)
{
printf("请输入第%d个数据:", temp - n);
scanf("%d", q++);
}
}
void print_data(int *q, int n)
{
// 打印数据
while (n--)
printf("%d ", *q++);
printf("\n");
}
int main()
{
int *p = NULL; // NULL == 0,用来表示指针指向的内存空间不存在
p = create_int_arr(10);
input_int_data(p, 10);
print_data(p, 10);
free(p); // 释放内存空间
return 0;
}

19
day11/d10.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = (char *)malloc(32);
p = (char *)realloc(p, 48);
if (NULL == p)
{
perror("malloc");
return 1;
}
// strncpy 用于将特定长度的字符串拷贝到指定的内存空间中
strncpy(p, "disen,jack,lucy", 10); // 将 disen 的前 3 个字符拷贝到 p 中
printf("%s\n", p);
free(p);
return 0;
}

30
day11/d11.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void strcp(char *dest, char *src)
{
int len = 0;
while (src[len++]) // 计算 src 的长度
;
for (int i = 0; i < len - 1; i++) // len-1 会去掉字符串末尾的'\0'
{
*(dest + i) = *(src + i); // dest[i] = src[i];
}
// dest 原内容多余的部分要清空
while (dest[len - 1])
{
dest[len - 1] = 0;
len++;
}
}
int main()
{
char p[100] = "disen,666,小马,888";
strcp(p, "disen,jack,lucy");
printf("%s\n", p);
return 0;
}

27
day11/d12.c Normal file
View File

@ -0,0 +1,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *str_cat(char *dest, char *src)
{
int insert_pos = 0;
while (dest[insert_pos])
insert_pos++;
// 在 dest 的第一个 '\0' 处插入 src 内容
for (int i = 0; i <= strlen(src); i++)
// for (int i = 0; *(src + i); i++)
{
dest[insert_pos++] = *(src + i);
}
return dest;
}
int main()
{
char p[100] = "good, 1\023";
str_cat(p, "小李子");
printf("%s\n", p);
return 0;
}

28
day11/d12_2.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 拷贝 src 的前 n 个字符到 dest 中
char *str_n_cat(char *dest, char *src, int n)
{
int insert_pos = 0;
while (dest[insert_pos])
insert_pos++;
// 在 dest 的第一个 '\0' 处插入 src 内容
for (int i = 0; i < n; i++)
// for (int i = 0; *(src + i); i++)
{
dest[insert_pos++] = *(src + i);
}
return dest;
}
int main()
{
char p[100] = "good, 1\023";
str_n_cat(p, "小李子", 6);
printf("%s\n", p);
return 0;
}

34
day11/d13.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 比较两个字符串,如果 s1 > s2返回 1如果 s1 < s2返回 -1如果 s1 == s2返回 0
int cmp(const char *s1, const char *s2)
{
while (*s1 && *s2)
{
if (*s1 > *s2) // 当前位置 *s1 > *s2
return 1;
else if (*s1 < *s2) // 当前位置 *s1 < *s2
return -1;
else // *s1 == *s2
{
s1++; // s1 指向下一个字符
s2++; // s2 指向下一个字符
}
}
if (*s1) // *s1 还有字符,*s2 没有字符
return 1;
if (*s2) // *s2 还有字符,*s1 没有字符
return -1;
return 0; // *s1 == *s2返回相等
}
int main()
{
char *p = "abc";
char *q = "abcd";
printf("%d\n", cmp(p, q));
return 0;
}

28
day11/d13_2.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// disen 版代码: 用于比较两个字符串,如果 s1 > s2返回 1如果 s1 < s2返回 -1如果 s1 == s2返回 0
int cmp(const char *s1, const char *s2)
{
int i = 0;
while ((s1[i] || s2[i]) && s1[i] == s2[i])
i++;
int delta = s1[i] - s2[i];
if (delta == 0)
return 0;
else if (delta > 0)
return 1;
else
return -1;
}
int main()
{
char *p = "abd";
char *q = "abcd";
printf("%d\n", cmp(p, q));
return 0;
}

29
day11/d13_3.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 比较两个字符串,如果 s1 > s2返回 1如果 s1 < s2返回 -1如果 s1 == s2返回 0
int ncmp(const char *s1, const char *s2, int n)
{
while (*s1 && *s2 && n--)
{
if (*s1 > *s2) // 当前位置 *s1 > *s2
return 1;
else if (*s1 < *s2) // 当前位置 *s1 < *s2
return -1;
else // *s1 == *s2
{
s1++; // s1 指向下一个字符
s2++; // s2 指向下一个字符
}
}
return 0; // *s1 == *s2返回相等
}
int main()
{
char *p = "abc";
char *q = "aacd";
printf("%d\n", ncmp(p, q, 3));
return 0;
}

16
day11/d14.c Normal file
View File

@ -0,0 +1,16 @@
// strchr 和 strstr 的使用
// strchr: 查找字符串中第一次出现某个字符的首地址位置
// strrchr: 查找字符串中最后一次出现某个字符的首地址位置(反向查找)
// strstr: 查找字符串中第一次出现某个字符串的首地址位置
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = "disen";
strchr(p, 's'); // 查找字符串中第一次出现某个字符的首地址位置
printf("%ld\n", strchr(p, 's') - p);
return 0;
}

22
day11/d15.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int valid_int(const char *s)
{
int n = atoi(s); // 转换成整型
int x = n / 100; // 百位
int y = n % 100 / 10; // 十位
int z = n % 10; // 个位
return (
x * x * x +
y * y * y +
z * z * z ==
n); // 水仙花数
}
int main(int argc, const char *argv[])
{
printf("%d\n", valid_int(argv[1]));
return 0;
}

13
day11/d16.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
char *p = "120";
printf("%ld\n", atol(p)); // atol: 转换成长整型
p = "12.3";
printf("%.2f\n", atof(p)); // atof: 转换成浮点数
return 0;
}

26
day11/d17.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[100] = "小明:21,,,.男.女,北京:haidian";
int i = 0;
char *delim = ":,."; // 以冒号、逗号、点号作为分隔符
char *ret[10];
ret[i] = strtok(str, delim); // 返回第一次切割的结果
while (ret[i] != NULL)
{
i++;
// 第二次及以后的切割要传入 NULL
ret[i] = strtok(NULL, delim);
}
char *title[10] = {"姓名", "年龄", "性别", "爱好", "地址", "区域"};
for (int j = 0; j < i; j++)
{
printf("%s: %s\n", title[j], ret[j]);
}
return 0;
}

30
day11/d2.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
char *create_char_arr(int n)
{
char *p = (char *)malloc(n * sizeof(char));
if (NULL == p)
{
perror("malloc error");
return NULL;
}
perror("malloc success");
return p;
}
void input_name(char **q)
{
printf("输入数据: ");
scanf("%s", *q);
}
int main()
{
char *p = NULL;
p = create_char_arr(20);
input_name(&p);
printf("输出数据: %s\n", p);
free(p);
return 0;
}

19
day11/d3.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *name = NULL;
name = (char *)malloc(32 * sizeof(char)); // 32个字节
if (NULL == name)
perror("malloc"); // 输出分配内存失败的原因
else
memset(name, 'a', 32); // 将 name 初始化为 32 个字节的 'a'
*(name + 30) = 'B';
*(name + 31) = '\0'; // 将 name 的最后一个字节设置为 '\0'
printf("%s\n", name);
free(name); // 释放内存空间
return 0;
}

16
day11/d4.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
int main()
{
char *name = NULL;
name = (char *)calloc(4, 8 * sizeof(char)); // 说明: 4 * 8 = 32
if (NULL == name)
perror("calloc");
scanf("%s", name);
printf("%s\n", name);
free(name);
return 0;
}

22
day11/d5.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
int main()
{
char(*names)[32] = (char(*)[32])calloc(3, 32 * sizeof(char)); // 说明: 4 * 32 = 128
for (int i = 0; i < 3; i++)
{
printf("第 %d 个人的名字: ", i + 1);
// names + i -> char(*)[32] 二维数组的首地址
// *(names + i) -> char[32] 一维数组的首地址 (*降维)
scanf("%s", *(names + i)); // *(names + i) == names[i]
}
for (int i = 0; i < 3; i++)
printf("%s\n", *(names + i)); // *(names + i) == names[i]
free(names);
return 0;
}

114
day11/d6.c Normal file
View File

@ -0,0 +1,114 @@
// 设计列表数据结构操作函数,包含创建空列表,列表添加、删除和修改等操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
// 定义链表节点
typedef struct node
{
char name[32];
struct node *next;
} Node;
// 创建空链表
Node *create_list()
{
Node *head = (Node *)malloc(sizeof(Node));
if (NULL == head)
{
perror("malloc error");
return NULL;
}
memset(head, 0, sizeof(Node));
return head;
}
// 添加节点
void add_node(Node *head, char *name)
{
Node *p = head;
while (p->next != NULL)
p = p->next;
Node *new_node = (Node *)malloc(sizeof(Node));
if (NULL == new_node)
{
perror("malloc error");
return;
}
memset(new_node, 0, sizeof(Node));
strcpy(new_node->name, name);
p->next = new_node;
}
// 打印链表
void print_list(Node *head)
{
Node *p = head->next;
while (p != NULL)
{
printf("%s ", p->name);
p = p->next;
}
printf("\n");
}
// 删除节点
void delete_node(Node *head, char *name)
{
Node *p = head;
while (p->next != NULL)
{
if (strcmp(p->next->name, name) == 0)
{
Node *temp = p->next;
p->next = p->next->next;
free(temp);
return;
}
p = p->next;
}
}
// 修改节点
void modify_node(Node *head, char *name, char *new_name)
{
Node *p = head->next;
while (p != NULL)
{
if (strcmp(p->name, name) == 0)
{
strcpy(p->name, new_name);
return;
}
p = p->next;
}
}
// 释放链表
void free_list(Node *head)
{
Node *p = head;
while (p != NULL)
{
Node *temp = p;
p = p->next;
free(temp);
}
}
int main()
{
Node *head = create_list();
add_node(head, "a");
add_node(head, "b");
add_node(head, "c");
add_node(head, "d");
print_list(head);
delete_node(head, "b");
print_list(head);
modify_node(head, "c", "e");
print_list(head);
free_list(head);
return 0;
}

65
day11/d6_2.c Normal file
View File

@ -0,0 +1,65 @@
// 设计列表数据结构操作函数,包含创建空列表,列表添加、删除和修改等操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
int *create_list(int cap_size)
{
int *p = (int *)malloc(cap_size * sizeof(int));
if (NULL == p)
perror("malloc error");
else
memset(p, 0, cap_size * sizeof(int));
return p;
}
int *add(int *p, int size, int element)
{
// 判断当前的空间是否已满
int i = 0;
while (i < size && p[i] != 0) // *(p+i) = p[i]
{
i++;
// 这里不能用 p++, 因为会改变地址偏移量
// p++;
}
if (i < size) // 空间未满
{
p[i] = element; // 将 element 添加到空间中
}
else if (i == size)
{
printf("空间已满, 开始扩容\n");
int *new_p = (int *)realloc(p, (size + 1) * sizeof(int)); // 重新分配空间
if (NULL == p)
perror("realloc error");
else
{
p = new_p;
p[i] = element;
}
return p;
}
}
int main()
{
int *p = create_list(4);
p[0] = 2, p[1] = 3, p[2] = 4;
for (int i = 0; i < 4; i++)
printf("%d ", *(p + i));
printf("\n");
add(p, 4, 100); // p[3] = 100;
add(p, 4, 200); // 100
add(p, 4, 300); // 100
add(p, 4, 400); // 100
for (int i = 0; i < 6; i++)
printf("%d ", *(p + i));
printf("\n");
free(p);
return 0;
}

36
day11/d6_3.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
int main()
{
// 定义字符数组,接收用户输入的内容(最大值为 100 B
char *p = (char *)malloc(100 * sizeof(char));
if (NULL == p)
{
perror("malloc");
return 1;
}
memset(p, 0, 100 * sizeof(char));
printf("data: ");
scanf("%s", p);
// strlen() 获取字符的个数
int len = 0;
while (p[len++])
; // len = strlen(p);
if (len != 100)
{
printf("before realloc,%p\n", p);
// 重新分配空间
p = (char *)realloc(p, (len) * sizeof(char));
printf("after realloc,%p\n", p);
}
printf("%s, size of p: %d\n", p, len); // 重新分配空间后p 的大小不变
free(p); // 释放空间
return 0;
}

27
day11/d7.c Normal file
View File

@ -0,0 +1,27 @@
// 内存泄漏
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
int *create(int n)
{
int *p = (int *)malloc(n * sizeof(int)); // n*4
memset(p, 0, n * sizeof(int));
if (NULL == p)
{
perror("malloc error");
}
return p;
}
int main()
{
int *p = create(5);
p[0] = 100;
printf("%d\n", *p); // *p = p[0]
// 用完之后,释放空间
free(p);
return 0; // p 指向的空间没有释放,内存泄漏
}

27
day11/d7_2.c Normal file
View File

@ -0,0 +1,27 @@
// 在 create 函数中申请的内存发生了泄漏
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
void create(char *p, int n)
{
p = (int *)malloc(n);
memset(p, '\0', n);
if (NULL == p)
{
perror("malloc error");
}
}
int main()
{
int *p = NULL;
create(p, 32);
scanf("%s", p);
printf("==>%s\n", p);
// 用完之后,释放空间
free(p);
return 0; // p 指向的空间没有释放,内存泄漏
}

23
day11/d7_3.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void create(char **p, int n) // **p = p[0]; *p = p[0]; p = &p[0]
{
*p = (char *)malloc(n); // *p = p[0]
memset(*p, '\0', n);
if (NULL == *p)
{
perror("malloc error");
}
}
int main()
{
char *p = NULL;
create(&p, 32);
scanf("%s", p);
printf("==>%s\n", p);
free(p);
return 0;
}

29
day11/d8.c Normal file
View File

@ -0,0 +1,29 @@
// 自定义函数 str_len计算字符串长度
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int str_len(const char *str)
{
// const 作用: 防止str指针在函数内被修改
int len = 0;
while (str[len++])
;
return len - 1; // 不需要 '\0'
}
int main()
{
char content[100] = "";
while (1)
{
printf("data: ");
scanf("%s", content);
if (content[0] == 'q')
break; // 当输入 q 时,退出循环
// printf("%s len is %d\n", content, str_len(content));
// string.h 中的 strlen 函数
printf("%s len is %ld\n", content, strlen(content));
}
return 0;
}

18
day11/d9.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = (char *)malloc(32);
if (NULL == p)
{
perror("malloc");
return 1;
}
// strcpy 用于字符串拷贝
strcpy(p, "disen");
printf("%s\n", p);
free(p);
return 0;
}