总结的C语言函数

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
int id; // 教师ID
int sex; // 教师性别
char* name; // 教师姓名
char** course_names; // 教师的课程的名字数组
int course_num; // 教师的课程的数量
} teachers;

typedef struct
{
int id; // 学生ID
char* name; // 学生姓名
float score; // 学生成绩
char** dog_names; // 学生的狗的名字数组
int dog_num; // 学生的狗的数量
teachers* teacher; // 学生的老师
int teacher_num; // 学生的老师的数量
} Student;

Student* create_student(void)
{
Student* student = (Student*)malloc(sizeof(Student)); // 分配学生结构体的内存
if (student == NULL)
{
printf("malloc failed!\n");
return NULL;
}
printf("allocated memory for student: 0x%p\n", student);

student->name = (char*)malloc(50 * sizeof(char)); // 分配学生姓名的内存
if (student->name == NULL)
{
printf("malloc failed!\n");
free(student);
return NULL;
}
strcpy(student->name, "Alice"); // 初始化学生姓名
printf("allocated memory for student name: %s, 0x%p\n", student->name, student->name);

student->dog_num = 4; // 初始化学生的狗的数量
printf("student->dog_num: %d\n", student->dog_num);
student->dog_names = (char**)malloc(student->dog_num * sizeof(char*)); // 分配学生的狗的名字数组的内存
printf("allocated memory for student dog names array: 0x%p\n", student->dog_names);
for (size_t i = 0; i < student->dog_num; i++)
{
student->dog_names[i] = (char*)malloc(50 * sizeof(char)); // 分配每个狗的名字的内存
snprintf(student->dog_names[i], 50, "dog%d", i); // 初始化每个狗的名字
}
for (size_t i = 0; i < student->dog_num; i++)
{
printf("dog%d: %s, 0x%p\n", i, student->dog_names[i], student->dog_names[i]);
}

student->teacher_num = 4; // 初始化学生的老师的数量
printf("student->teacher_num: %d\n", student->teacher_num);
student->teacher = (teachers*)malloc(student->teacher_num * sizeof(teachers)); // 分配学生的老师的结构体数组的内存
printf("allocated memory for student teacher array: 0x%p\n", student->teacher);
for (size_t i = 0; i < student->teacher_num; i++)
{
printf("------ teacher%d 0x%p ------\n", i, &student->teacher[i]);
student->teacher[i].id = i + 1; // 初始化每个老师的ID
student->teacher[i].name = (char*)malloc(50 * sizeof(char)); // 分配每个老师的姓名的内存
snprintf(student->teacher[i].name, 50, "teacher%d", i); // 初始化每个老师的姓名
printf("allocated memory for teacher%d name: 0x%p\n", i, student->teacher[i].name);

student->teacher[i].course_num = 3; // 初始化每个老师的课程的数量
printf("teacher%d->course_num: %d\n", i, student->teacher[i].course_num);
student->teacher[i].course_names = (char**)malloc((student->teacher[i].course_num) * sizeof(char*)); // 分配每个老师的课程的名字数组的内存
printf("allocated memory for teacher%d course names array: 0x%p\n", i, student->teacher[i].course_names);
for (size_t j = 0; j < student->teacher[i].course_num; j++)
{
student->teacher[i].course_names[j] = (char*)malloc(50 * sizeof(char)); // 分配每个课程的名字的内存
snprintf(student->teacher[i].course_names[j], 50, "course%d-%d", i, j); // 初始化每个课程的名字
printf ("allocated memory for course%d-%d name: 0x%p\n", i, j, student->teacher[i].course_names[j]);
}
}

printf("------ student malloc end ------\n");
return student;
}

int main()
{
Student* student = create_student();

return 0;
}

释放内存的函数

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
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define RELEASE_MEMORY(ptr) \
releaseMemory((void**)&ptr);

void releaseMemory(void** ptr)
{
if (ptr == NULL)
{
printf("pointer 0x%p is null.\n", ptr);
return;
}

if (*ptr == NULL)
{
printf("freeing 0x%p (null pointer).\n", *ptr);
return;
}

printf("freeing 0x%p\n", *ptr);
free(*ptr);
*ptr = NULL;
}

int main()
{
char* str_NULL = NULL;
RELEASE_MEMORY(str_NULL);

int* array = (int*)malloc(10 * sizeof(int)); // 动态分配内存
if (array == NULL)
{
printf("Memory allocation failed.\n");
return 1;
}
printf("address of array before freeing: %p\n", array);
RELEASE_MEMORY(array); // 释放内存
printf("address of array after freeing: %p\n", array);

char* str = (char*)malloc(100 * sizeof(char)); // 动态分配内存
if (str == NULL)
{
printf("Memory allocation failed.\n");
return 1;
}
memcpy(str, "Hello, world!", 13); // 复制字符串到内存中
printf("string: %s\n", str);
printf("address of str: %p\n", str);
RELEASE_MEMORY(str); // 释放内存
printf("string: %s\n", str);
printf("address of str: %p\n", str);

return 0;
}

释放内存数组的函数

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void releaseMemory(void** ptr)
{
if (ptr == NULL)
{
printf("pointer 0x%p is null.\n", ptr);
return;
}

if (*ptr == NULL)
{
printf("freeing 0x%p (null pointer).\n", *ptr);
return;
}

printf("freeing 0x%p\n", *ptr);
free(*ptr);
*ptr = NULL;
}

void releaseArray(void*** ptrArray, int* size)
{
if (ptrArray == NULL)
{
printf("ptrArray 0x%p is null.\n", ptrArray);
return;
}

if (*ptrArray == NULL)
{
printf("freeing 0x%p (null pointer).\n", *ptrArray);
return;
}

// 逐个释放每个字符串
printf("ptrArray 0x%p, size: %d\n",*ptrArray, *size);
for (int i = 0; i < *size; i++)
{
releaseMemory((void**)&((*ptrArray)[i]));
}

// 释放字符串数组本身
printf("freeing ptrArray 0x%p\n", *ptrArray);
free(*ptrArray);
*ptrArray = NULL;
*size = 0;
}

int main()
{
int size = 4; // 字符串数组的大小
char** strArray = (char**)malloc(size * sizeof(char*)); // 分配字符串数组的内存

// 检查内存分配是否成功
if (strArray == NULL)
{
printf("malloc failed!\n");
return 1;
}

// 为每个字符串分配内存
for (int i = 0; i < size; i++)
{
strArray[i] = (char*)malloc(50 * sizeof(char)); // 假设每个字符串最大长度为49(1个字符用于空字符结束)

// 检查内存分配是否成功
if (strArray[i] == NULL)
{
printf("内存分配失败!\n");

// 释放已分配的内存
for (int j = 0; j < i; j++)
{
free(strArray[j]);
}
free(strArray);
return 1;
}
}

// 初始化字符串
strcpy(strArray[0], "Hello, world!");
strcpy(strArray[1], "Welcome to C programming.");
strcpy(strArray[2], "This is a dynamically allocated string array.");
strcpy(strArray[3], "Enjoy coding!");

// 打印字符串数组内容
printf("字符串数组内容:\n");
for (int i = 0; i < size; i++)
{
printf("%s\n", strArray[i]);
}

releaseArray((void***)&strArray, &size); // 释放字符串数组的内存
printf("strArray 0x%p is released.\n", strArray);
printf("size of strArray: %d\n", size);

return 0;
}

各类格式化输出

%zu:以无符号整型格式输出size_t类型变量。%zu 是一个格式说明符,用于 printf 系列函数中,专门用于输出 size_t 类型的值。size_t 是一种无符号整数类型,通常用于表示对象的大小或数组的长度。使用 %zu 可以确保在打印时与 size_t 类型的大小相匹配,避免潜在的类型不匹配问题,从而使代码更加安全和可移植。

%c 是 C 语言中格式化输出的一个格式说明符,用于在 printf、fprintf、sprintf 等函数中输出单个字符。其基本用法如下:

%x 用于以小写十六进制格式输出整数值。它通常用于指针或整型数据的打印。例如,如果你有一个整型变量并希望以十六进制格式输出,可以使用 %x。
例如:如果有一个整数 255,使用 printf(“%x”, 255); 会输出 ff。

%p 用于输出指针的值,通常用于显示内存地址。输出的格式依赖于实现,通常是以十六进制表示。
例如:如果你有一个指针变量 int* ptr,你可以使用 printf(“%p”, (void*)ptr); 来输出指针的地址。

输入十六进制的字符串,转为字节数组

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 将返回值作为输出参数
void hexStringToByteArray(const char* hexString, unsigned char** outputByteArray, size_t* outputByteArraySize)
{
// 确保输入字符串不为空
if (hexString == NULL)
{
printf("input hexString is null.\n");
return;
}

size_t length = strlen(hexString);

// 检查输入长度是否为偶数
if (length % 2 != 0)
{
printf("input hexString length is not even.\n");
return;
}

// 校验字符是否为合法的十六进制字符
for (size_t i = 0; i < length; i++)
{
if (!isxdigit((unsigned char)hexString[i]))
{
printf("input hexString contains non-hexadecimal characters.\n");
return;
}
}

size_t byteArraySize = length / 2;

// 使用calloc分配内存
unsigned char* byteArray = (unsigned char*)calloc(byteArraySize, sizeof(unsigned char));
if (byteArray == NULL)
{
printf("malloc failed.\n");
return;
}

// 将十六进制字符串转换为字节数组
for (size_t i = 0; i < length / 2; i++)
{
sscanf(hexString + 2 * i, "%2hhx", &byteArray[i]);
}

// 计算字节数组的长度和赋值给输出参数
*outputByteArraySize = byteArraySize;
*outputByteArray = byteArray; // 将临时数组赋值给输出参数
}

int main()
{
const char* hexString = "4A61636B"; // 输入的十六进制字符串
size_t byteArraySize = 0;
unsigned char* byteArray = NULL;

hexStringToByteArray(hexString, &byteArray, &byteArraySize); // 修改后的函数调用

if (byteArray != NULL)
{
printf("output byte array: ");
for (size_t i = 0; i < byteArraySize; i++)
{
printf("%02X ", byteArray[i]);
}
printf("\n");

// 释放分配的内存
free(byteArray);
byteArray = NULL;
}

return 0;
}

将字节数组转为十六进制的字符串

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void readFileDataBinary(const char* filename, unsigned char** data, size_t* dataSize)
{
// 以二进制方式打开文件
FILE* file = fopen(filename, "rb");
if (file == NULL)
{
perror("无法打开文件");
return;
}

// 获取文件大小
fseek(file, 0, SEEK_END);
long fileSize = ftell(file); // 获取文件大小
fseek(file, 0, SEEK_SET); // 重置文件指针到开头

// 动态分配内存来存储文件内容
*data = (unsigned char*)malloc(fileSize);
if (*data == NULL)
{
perror("内存分配失败");
fclose(file);
return;
}

// 读取文件内容到缓冲区
*dataSize = fread(*data, sizeof(unsigned char), fileSize, file);

// 关闭文件
fclose(file);
}

void freeFileData(unsigned char** data)
{
if (data != NULL && *data != NULL)
{
free(*data); // 释放分配的内存
*data = NULL; // 将指针设为NULL,避免悬挂指针
}
}

// 辅助函数:将字节数组转换为十六进制字符串
char* bytes_to_hex_string(const unsigned char* bytes, size_t length)
{
// 动态分配内存:每个字节2个字符 + 1个null字符
char* hex_str = (char*)malloc(length * 2 + 1);
if (hex_str == NULL)
{
printf("Memory allocation failed.\n");
return NULL; // 如果内存分配失败,返回NULL
}

for (size_t i = 0; i < length; i++)
{
sprintf(&hex_str[i * 2], "%02x", bytes[i]);
}
hex_str[length * 2] = '\0'; // 确保字符串以null字符结尾

return hex_str;
}

void _STRING_FREE_func(char** string)
{
if (string != NULL && *string != NULL)
{
printf("Freeing string: %s\n", *string);
free(*string);
*string = NULL;
printf("String freed.\n");
}
else
{
printf("String is null.\n");
}
}

int main()
{
// 示例文件名
const char* filename = "tempCodeRunnerFile.c"; // 替换为你的文件名
unsigned char* fileData = NULL; // 用于保存读取的文件数据
size_t fileDataSize = 0; // 用于保存读取的数据大小

readFileDataBinary(filename, &fileData, &fileDataSize);

printf("Read file data: %zu bytes\n", fileDataSize);

char* hex_string = bytes_to_hex_string(fileData, fileDataSize);

printf("Hexadecimal string: %s\n", hex_string);

printf("lendth of hex_string: %d\n",strlen(hex_string));

freeFileData(&fileData); // 释放分配的内存

_STRING_FREE_func(&hex_string); // 释放字符串内存

// ------------------------------

// 示例字节数组
unsigned char bytes[] = {0xAB, 0xCD, 0xEF, 0x01, 0x23};
size_t length = sizeof(bytes) / sizeof(bytes[0]);

// 调用转换函数
hex_string = bytes_to_hex_string(bytes, length);
if (hex_string != NULL)
{
// 打印十六进制字符串
printf("Hexadecimal string: %s\n", hex_string);
// 释放分配的内存
_STRING_FREE_func(&hex_string);
}
else
{
printf("Memory allocation failed.\n");
}

return 0;
}

读取二进制文件的数据以十六进制输出

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void readFileDataBinary(const char* filename, unsigned char** data, size_t* dataSize)
{
// 以二进制方式打开文件
FILE* file = fopen(filename, "rb");
if (file == NULL)
{
perror("无法打开文件");
return;
}

// 获取文件大小
fseek(file, 0, SEEK_END);
long fileSize = ftell(file); // 获取文件大小
fseek(file, 0, SEEK_SET); // 重置文件指针到开头

// 动态分配内存来存储文件内容
*data = (unsigned char*)malloc(fileSize);
if (*data == NULL)
{
perror("内存分配失败");
fclose(file);
return;
}

// 读取文件内容到缓冲区
*dataSize = fread(*data, sizeof(unsigned char), fileSize, file);

// 关闭文件
fclose(file);
}

void freeFileData(unsigned char** data)
{
if (data != NULL && *data != NULL)
{
free(*data); // 释放分配的内存
*data = NULL; // 将指针设为NULL,避免悬挂指针
}
}

void printFileBinaryDataToHEX(const unsigned char* data, size_t dataSize, int printBufferSize)
{
if (printBufferSize < 0)
{
printf("printBufferSize cannot be negative.\n");
return;
}

if (data != NULL && dataSize > 0)
{
size_t bufferSize = (printBufferSize <= 0) ? (dataSize * 3) : (printBufferSize * 3);
char* buffer = (char*)calloc(bufferSize + 1, sizeof(char));
if (buffer == NULL)
{
printf("malloc failed.\n");
return;
}

// 打印每个字节的16进制值
for (size_t i = 0; i < dataSize; i++)
{
if (printBufferSize == 0)
{
sprintf(&buffer[i * 3], "%02X ", data[i]);
}
else
{
sprintf(&buffer[i % printBufferSize * 3], "%02X ", data[i]);

if (i % printBufferSize == printBufferSize - 1)
{
printf("%s\n", buffer);
(memsetbuffer, 0, bufferSize + 1); // 清空缓冲区
}
}
}

// 打印剩余的字节
if (dataSize % printBufferSize != 0)
{
printf("%s\n", buffer);
}

// 释放缓冲区
free(buffer);
buffer = NULL;
}
else
{
printf("data is empty.\n");
}
}

int main()
{
const char* filename = "tempCodeRunnerFile.c"; // 替换为你的文件名
unsigned char* data = NULL; // 用于保存读取的文件数据
size_t dataSize = 0; // 用于保存读取的数据大小

readFileDataBinary(filename, &data, &dataSize);

printf("读取的字节数: %zu 字节\n", dataSize);

printFileBinaryDataToHEX(data, dataSize, 18); // 打印每个字节的16进制值

printf("data :%p\n", data);

freeFileData(&data); // 释放内存

printf("data :%p\n", data);

return 0;
}

释放字符串的函数

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

void _STRING_FREE_func(char** string)
{
if (string != NULL && *string != NULL)
{
printf("Freeing string: %s\n", *string);
free(*string);
*string = NULL;
printf("String freed.\n");
}
else
{
printf("String is null.\n");
}
}

int main()
{
// 动态分配内存并初始化字符串
char* myString = malloc(50 * sizeof(char));
if (myString == NULL)
{
fprintf(stderr, "Memory allocation failed\n");
return 1;
}

// 设置字符串内容
snprintf(myString, 50, "Hello, World!");
printf("Original string: %s\n", myString);

// 释放字符串并将指针设置为NULL
_STRING_FREE_func(&myString);

// 验证指针是否为NULL
if (myString == NULL)
{
printf("myString is now NULL.\n");
}
else
{
printf("myString is not NULL: %s\n", myString);
}

return 0;
}

释放字符串数组的函数

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

void releaseStringArray(char*** array, int* size)
{
// 释放每个字符串的内存
for (int i = 0; i < *size; i++)
{
free((*array)[i]);
(*array)[i] = NULL; // 将指针置为 NULL,避免悬空指针
}
// 释放字符串数组本身的内存
free(*array);
*array = NULL; // 将数组指针置为 NULL,避免悬空指针
*size = 0; // 数组大小置为 0
printf("String array released.\n");
}

int main()
{
int size = 4;
// 创建一个指向字符串的指针数组
char** strings = malloc(size * sizeof(char*));

// 为每个字符串分配内存
strings[0] = malloc(6 * sizeof(char)); // "Hello"
strings[1] = malloc(6 * sizeof(char)); // "World"
strings[2] = malloc(7 * sizeof(char)); // "Fitten"
strings[3] = malloc(5 * sizeof(char)); // "Code"

// 复制字符串到数组
snprintf(strings[0], 6, "Hello");
snprintf(strings[1], 6, "World");
snprintf(strings[2], 7, "Fitten");
snprintf(strings[3], 5, "Code");

// 打印字符串数组
printf("String array size:%d\n", size);
printf("String array:\n");
for (int i = 0; i < size; i++)
{
printf("%s\n", strings[i]);
}

// 释放字符串数组
releaseStringArray(&strings, &size);

printf("String array size:%d\n", size);

return 0;
}

传入指针,修改字符串值的函数

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

// 函数定义
void modify_value(int* ptr, char** str)
{
if (ptr != NULL)
{
*ptr = 20; // 修改指针所指向的值
}
else
{
printf("传入的指针为空。\n");
}

if (str != NULL)
{
*str = "text2"; // 修改指针所指向的字符串
}
else
{
printf("传入的字符串指针为空。\n");
}
}

int main()
{
int value = 10; // 初始化一个整型变量
printf("before modify: %d\n", value);

char* my_string = "text1";
printf("before modify: %s\n", my_string);

modify_value(&value, &my_string); // 传入整型变量的地址

printf("after modify: %d\n", value);
printf("after modify: %s\n", my_string);
return 0;
}

普通的枚举

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

typedef enum {
RESPONSE_OK = 200, // 请求成功
RESPONSE_CREATED = 201, // 资源创建成功
RESPONSE_ACCEPTED = 202, // 请求已接受,待处理
RESPONSE_NO_CONTENT = 204, // 请求成功,但无返回内容
RESPONSE_BAD_REQUEST = 400, // 客户端请求有语法错误
RESPONSE_UNAUTHORIZED = 401, // 未授权访问
RESPONSE_FORBIDDEN = 403, // 禁止访问
RESPONSE_NOT_FOUND = 404, // 请求的资源未找到
RESPONSE_INTERNAL_ERROR = 500, // 服务器内部错误
RESPONSE_NOT_IMPLEMENTED = 501 // 服务器不支持请求的方法
} ResponseCode;

int main() {
ResponseCode code = RESPONSE_OK;

switch (code) {
// 在 switch 语句中,直接使用 RESPONSE_OK 来表示这些枚举值,而不是 ResponseCode.RESPONSE_OK。
// case ResponseCode.RESPONSE_OK:
// printf("响应码: %d, 表示请求成功。\n", code);
// break;
case RESPONSE_OK:
printf("响应码: %d, 表示请求成功。\n", code);
break;
case RESPONSE_BAD_REQUEST:
printf("响应码: %d, 表示请求有语法错误。\n", code);
break;
case RESPONSE_NOT_FOUND:
printf("响应码: %d, 表示请求的资源未找到。\n", code);
break;
default:
printf("响应码: %d, 表示未知响应。\n", code);
break;
}

return 0;
}
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
#include <stdio.h>

enum {
RESPONSE_OK = 200, // 请求成功
RESPONSE_CREATED = 201, // 资源创建成功
RESPONSE_ACCEPTED = 202, // 请求已接受,待处理
RESPONSE_NO_CONTENT = 204, // 请求成功,但无返回内容
RESPONSE_BAD_REQUEST = 400, // 客户端请求有语法错误
RESPONSE_UNAUTHORIZED = 401, // 未授权访问
RESPONSE_FORBIDDEN = 403, // 禁止访问
RESPONSE_NOT_FOUND = 404, // 请求的资源未找到
RESPONSE_INTERNAL_ERROR = 500, // 服务器内部错误
RESPONSE_NOT_IMPLEMENTED = 501 // 服务器不支持请求的方法
};

int main() {
int code = RESPONSE_OK;

switch (code) {
case RESPONSE_OK:
printf("响应码: %d, 表示请求成功。\n", code);
break;
case RESPONSE_BAD_REQUEST:
printf("响应码: %d, 表示请求有语法错误。\n", code);
break;
case RESPONSE_NOT_FOUND:
printf("响应码: %d, 表示请求的资源未找到。\n", code);
break;
default:
printf("响应码: %d, 表示未知响应。\n", code);
break;
}

return 0;
}

给url添加参数

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef enum {
EXECUTION_SUCCESS = 0, // 执行成功
EXECUTION_FAILURE = 1, // 执行失败
EXECUTION_INVALID_INPUT = 2, // 输入无效
EXECUTION_MEMORY_ERROR = 3, // 内存错误
EXECUTION_NOT_FOUND = 4, // 找不到资源
EXECUTION_TIMEOUT = 5, // 超时错误
EXECUTION_UNAUTHORIZED = 6, // 未授权
EXECUTION_UNKNOWN_ERROR = 7 // 未知错误
} ExecutionResults;

/**
* @brief 将字符串编码为 URL 编码形式。
*
* @param str 要编码的字符串。
* @return char* 编码后的字符串。需要释放返回的字符串内存。
*/
char* url_encode(const char* str)
{
size_t len = strlen(str);

// 预估最大可能需要的长度,由于每个字符最多编码为3个字符(%XX),加上一个结束符。
char* encoded = (char*)calloc(len * 3 + 1, sizeof(char));
if (encoded == NULL)
{
printf("'encoded' memory allocation failed!\n");
return encoded;
}

// 遍历字符串,将不安全字符编码为 %XX 形式。
char* ptr = encoded;
for (size_t i = 0; i < len; i++)
{
if (isalnum((unsigned char)str[i]) || strchr("-_.~", str[i]))
{
// 直接复制安全字符。
*ptr++ = str[i];
}
else
{
// 不安全的字符编码为 %XX 形式。
ptr += sprintf(ptr, "%%%02X", (unsigned char)str[i]);
}
}
*ptr = '\0'; // 结束字符串

// 返回编码后的字符串
return encoded;
}

typedef struct _RequestParameters
{
char* paramName; // 参数名
char* paramValue; // 参数值
} RequestParameters;

typedef struct _urlObject
{
char* url;
RequestParameters* parameters; // url带有的参数
size_t parameters_count; // 参数数量
} urlObject;

void url_FreeObject(urlObject* obj);
int urlUpdate(urlObject* urlObj, const char* key, const char* value);

urlObject* url_CreateObject(const char* url)
{
urlObject* obj = NULL;

// 使用 calloc 分配内存
obj = (urlObject*)calloc(1, sizeof(urlObject));
if (obj == NULL)
{
printf("'obj' memory allocation failed!\n");
goto BAD_END;
}

// 检查输入有效性
if (url != NULL)
{
// 分配适当的内存用于存储 URL 字符串
obj->url = (char*)calloc(strlen(url) + 1, sizeof(char));
if (obj->url == NULL)
{
printf("'obj->url' memory allocation failed!\n");
goto BAD_END;
}

// 将输入的 URL 字符串复制到结构体中
strcpy(obj->url, url);
}

return obj;

BAD_END:
url_FreeObject(obj);

return obj;
}

// 记得添加一个释放对象的函数
void url_FreeObject(urlObject* obj)
{
if (obj)
{
// 释放 URL 字符串
if (obj->url != NULL)
{
free(obj->url);
obj->url = NULL;
}

// 释放参数列表
if (obj->parameters != NULL)
{
for (size_t i = 0; i < obj->parameters_count; i++)
{
if (obj->parameters[i].paramName != NULL)
{
free(obj->parameters[i].paramName);
obj->parameters[i].paramName = NULL;
}
if (obj->parameters[i].paramValue != NULL)
{
free(obj->parameters[i].paramValue);
obj->parameters[i].paramValue = NULL;
}
}
free(obj->parameters);
obj->parameters = NULL;
}
obj->parameters_count = 0;

// 释放结构体对象
if (obj->url != NULL)
{
free(obj);
obj = NULL;
}
}
}

void urlAddNumberParam(urlObject* obj, const char* name, int value)
{

}

void urlAddStringParam(urlObject* obj, const char* name, const char* value)
{
char* newName =NULL;
char* newValue =NULL;
RequestParameters* newParams = NULL;

// 检查输入有效性
if (obj == NULL || name == NULL || value == NULL)
{
printf("Invalid input!\n");
return;
}

printf("Current parameter count:%d\n", obj->parameters_count);
printf("Add parameter name:%s, value:%s\n", name, value);

// 复制参数名
newName = strdup(name);
if (newName == NULL)
{
printf("'newName' memory allocation failed!\n");
goto BAD_END;
}

// 复制参数值
newValue = strdup(value);
if (newValue == NULL)
{
printf("'newValue' memory allocation failed!\n");
goto BAD_END;
}

// 计算新的参数列表大小
int currentSize = obj->parameters_count;

// 为新的参数列表分配内存
newParams = calloc(currentSize + 1, sizeof(RequestParameters));
if (newParams == NULL)
{
printf("'newParams' memory allocation failed!\n");
goto BAD_END;
}

// 复制参数列表,让旧的数据也指向新的参数列表
memcpy(newParams, obj->parameters, obj->parameters_count * sizeof(RequestParameters));

// 添加新的参数
newParams[currentSize].paramName = newName;
newParams[currentSize].paramValue = newValue;

// 修改url成功
if (urlUpdate(obj, newName, newValue) != EXECUTION_SUCCESS)
{
printf("Update url failed!\n");
goto BAD_END;
}

free(obj->parameters); // 释放旧的参数列表
obj->parameters= newParams; // 保存新的参数列表
obj->parameters_count = currentSize + 1; // 更新参数数量

printf("Update url success! Current parameter count:%d\n", obj->parameters_count);

// 打印参数列表
for (size_t i = 0; i < obj->parameters_count; i++)
{
printf("param[%d] name:%s, value:%s\n",i, newParams[i].paramName, newParams[i].paramValue);
}

return;

BAD_END:

if (newName != NULL)
{
free(newName);
newName = NULL;
}

if (newValue != NULL)
{
free(newValue);
newValue = NULL;
}

if (newParams != NULL)
{
free(newParams);
newParams = NULL;
}
}

int urlUpdate(urlObject* urlObj, const char* key, const char* value)
{
int ret = EXECUTION_FAILURE;
char* encoded_value = NULL;

// 检查输入有效性
if (urlObj == NULL || key == NULL || value == NULL)
{
printf("Invalid input!\n");
ret = EXECUTION_INVALID_INPUT;
goto END;
}

encoded_value = url_encode(value);
if (encoded_value == NULL)
{
printf("url encode failed.\n");
goto END;
}

char* connector_symbol = (urlObj->parameters_count == 0) ? "?" : "&";
char* assignment_symbol = "=";

// 动态分配足够大的内存来存放拼接后的 URL
size_t url_length = strlen(urlObj->url)
+ strlen(connector_symbol)
+ strlen(key)
+ strlen(assignment_symbol)
+ strlen(encoded_value);
char* full_url = (char*)calloc(url_length + 1, sizeof(char)); // +1 是为了 '\0'
if (full_url == NULL)
{
printf("'full_url' memory allocation failed!\n");
goto END;
}

// 拼接 URL
strcat(full_url, urlObj->url);
strcat(full_url, connector_symbol);
strcat(full_url, key);
strcat(full_url, assignment_symbol);
strcat(full_url, encoded_value);

// 释放 URL 字符串
if (urlObj->url != NULL)
{
free(urlObj->url);
}
urlObj->url = full_url; // 保存拼接后的 URL 字符串

END:
if (encoded_value != NULL)
{
free(encoded_value);
encoded_value = NULL;
}

return EXECUTION_SUCCESS;
}

int main()
{
/*
char* to_be_encoded_string = "HCOcWqfbB4JN3SsIhqL5mqfgVnknJcvNy84atN37RTGpUv2SrFRBR3VVms6vlFePkb0ybIiW9XanwYv5mo1KgnpeY185vH0FUZD17MrOgULSk//LG//fcKA/1PbTMHbL0L41KP8CCq6z6to5I+iwadj/EJlEwLbAKhupr6VCbyQ8==<c8SDcib2XcgNtQ4ur3W7Z7STYokDj+TyqK1d8P7Nb/2XMgvDAgelFnmT5HWzl0Lg6CbzIeEFmlTjmbrh3UcMg0JG6V1ISirJf1MKrDk6JLtTSdJa1BwLFNbaRuqkdgBV2PPtsVhs9ux1fyNkWucr/qMWEDRm98jLmeYROYdxYQXPRieNDq+nFq7xkktZQ8hKeRCVQYrVgaJ3Otr2nBw5Vq54lG0NBy6OL505HRZoDIzvQ+FxF2G6ch48sqYrI1xQFXxyMYBgijPKOLKVhYTp9g==";

char * encoded_string = url_encode(to_be_encoded_string);
printf("Encoded string: %s\n", encoded_string);

return 0;
*/

const char* base_url = "https://gateway.danaai.net:9443/auth/open-id/form";
const char* open_id = "HCOcWqfbB4JN3SsIhqL5mqfgVnknJcvNy84atN37RTGpUv2SrFRBR3VVms6vlFePkb0ybIiW9XanwYv5mo1KgnpeY185vH0FUZD17MrOgULSk//LG//fcKA/1PbTMHbL0L41KP8CCq6z6to5I+iwadj/EJlEwLbAKhupr6VCbyQ8==<c8SDcib2XcgNtQ4ur3W7Z7STYokDj+TyqK1d8P7Nb/2XMgvDAgelFnmT5HWzl0Lg6CbzIeEFmlTjmbrh3UcMg0JG6V1ISirJf1MKrDk6JLtTSdJa1BwLFNbaRuqkdgBV2PPtsVhs9ux1fyNkWucr/qMWEDRm98jLmeYROYdxYQXPRieNDq+nFq7xkktZQ8hKeRCVQYrVgaJ3Otr2nBw5Vq54lG0NBy6OL505HRZoDIzvQ+FxF2G6ch48sqYrI1xQFXxyMYBgijPKOLKVhYTp9g==";
const char* type = "cdk";

urlObject* urlObj = url_CreateObject(base_url);
if (urlObj == NULL)
{
printf("create object failed.\n");
return 1;
}

urlAddStringParam(urlObj, "open_id", open_id);
urlAddStringParam(urlObj, "type", type);
urlAddStringParam(urlObj, "type1", "type1_value");
urlAddStringParam(urlObj, "type2", "type2_value");

if (urlObj != NULL)
{
printf("Final URL: %s\n", urlObj->url);
url_FreeObject(urlObj); // 释放对象
}

return 0;
}