作为一名志在嵌入式开发的工程师,纯 C 语言依然是核心武器。一周内我手写近 3400 行代码,涵盖了指针深度应用、数据结构、算法套路和底层 API 重写,从野指针到内存拷贝,从链表操作到快速排序,从自定义字符串函数到递归回溯,今天我将这趟学习之旅总结成一篇理性且易读的技术贴,给同路人一些思路与参考。
哥们儿从5月1号一直跟到5月26号!5月20号更新!大家是不是都跟对象约会去了哥们儿没对象所以可以老老实实写代码哈哈哈哈哈哈!这还不值得点赞关注收藏吗
本文总结了嵌入式开发中C语言的核心知识体系,涵盖指针、数据结构、算法和底层API实现等关键内容。作者在一周内手写了3400行代码,重点包括:
技术亮点:
适合希望系统掌握嵌入式C开发核心技能的工程师参考学习。全文采用问题驱动式讲解,附带完整可运行的代码实现。
环境与整体架构
指针与内存:野指针、算术、关系
栈与链表:基础数据结构
排序与查找:快速排序 + qsort
字符串 API 重写:strncpy
/ strncat
/ strncmp
/ strchr
/ strstr
递归与回溯:斐波那契、全排列、N 皇后
实用小工具:动态分配、函数指针、二维数组传参
嵌入式关注:内存泄漏、防 nullptr
一周心得与建议
结语
一周 700 行代码覆盖了指针进阶、数据结构、算法套路、高级 API 重写等 20+ 知识点,本文将以亲测有效的模块化方式,结合常见原题与当下 C 语言面试高频点,每次分享约 6666 字与 500 行精选源码,分三篇完成总计约 20000 字与 1500 行示例,让你在短时间内掌握嵌入式开发所需的核心技巧。
指针与内存管理(野指针、空指针、算术、关系)
栈与链表(静态栈、头插链表、多级指针)
排序算法(快速排序、qsort、优化技巧)
自建字符串库(strncpy、strncat、strncmp、strchr、strstr)
动态内存示例(malloc / calloc / realloc / free)
代码量:约 500 行
文字量:约 6666 字
void wild_pointer_cause() {
int local = 42;
int *p1 = &local;
int *p2 = malloc(sizeof(int) * 1);
free(p2);
// p2 现在成为野指针,访问 *p2 将发生未定义行为
p2 = NULL; // 修复方式:置为 NULL
}
要点:malloc
后及时 free
并置 NULL
,避免野指针。
void null_pointer_demo() {
int *p = NULL;
if (!p) {
printf("指针为空,不能解引用\n");
}
}
要点:访问前检查,避免崩溃。
void pointer_arithmetic() {
int arr[5] = {1,2,3,4,5};
int *p = arr;
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(p + i));
}
}
避免越界;最好配合 sizeof(arr)/sizeof(arr[0])
。
void pointer_relation() {
int arr[5];
int *p1 = arr + 1;
int *p2 = arr + 3;
printf("p1 < p2 = %s\n", (p1 < p2)?"true":"false");
}
同一数组内比较指针合法。
#define MAX_STACK 100
struct Stack { int data[MAX_STACK]; int top; };
void initStack(struct Stack *s) { s->top = -1; }
bool isEmpty(struct Stack *s) { return s->top < 0; }
bool isFull(struct Stack *s) { return s->top >= MAX_STACK-1; }
void pushStack(struct Stack *s,int v){ if(!isFull(s)) s->data[++s->top]=v; }
int popStack(struct Stack *s){ return isEmpty(s)?-1:s->data[s->top--]; }
// 测试
void test_stack(){
struct Stack s;
initStack(&s);
for(int i=0;i<5;i++) pushStack(&s,i);
while(!isEmpty(&s)) printf("pop: %d\n", popStack(&s));
}
面试点:栈的边界检查和返回值策略。
struct Node{
int value;
struct Node *next;
struct Node **children;
int child_count;
};
// 头插法
struct Node* insertFirst(struct Node *head,int v){
struct Node* n=malloc(sizeof *n);
n->value=v; n->next=head;
n->children=NULL; n->child_count=0;
return n;
}
void printList(struct Node *h){
while(h){ printf("%d->",h->value); h=h->next; }
puts("NULL");
}
void test_list(){
struct Node* head=NULL;
head = insertFirst(head, 3);
head = insertFirst(head, 5);
printList(head);
}
多级指针:children
可动态扩容存储子节点。
void swap(int *a,int*b){int t=*a;*a=*b;*b=t;}
int partition(int a[],int lo,int hi){
int pivot=a[hi], i=lo-1;
for(int j=lo;j
优化:随机选 pivot、尾递归。
qsort
int cmpInt(const void*a,const void*b){ return *(int*)a - *(int*)b; }
void test_qsort(){
int a[]={5,2,8,3,1};
qsort(a,5,sizeof*a,cmpInt);
for(int i=0;i<5;i++) printf("%d ",a[i]);
puts("");
}
面试常考 qsort
用法及性能对比。
my_strncpy
char *my_strncpy(char *dst,const char*src,size_t n){
size_t i=0;
for(;i
区别:标准 strncpy
不保证尾部 \0
。
my_strncat
char *my_strncat(char*dst,const char*src,size_t n){
size_t i=strlen(dst), j=0;
for(;j
my_strncmp
int my_strncmp(const char*s1,const char*s2,size_t n){
for(size_t i=0;i
my_strchr
/ my_strstr
char *my_strchr(const char*s,int c){
while(*s){ if(*s==(char)c) return (char*)s; s++; }
return c=='\0'? (char*)s:NULL;
}
char *my_strstr(const char*h,const char*n){
if(!*n) return (char*)h;
for(;*h;h++){
const char *p=h,*q=n;
while(*p && *q && *p==*q){p++;q++;}
if(!*q) return (char*)h;
}
return NULL;
}
完全复刻标准行为,边界条件处理勿忘。
void test_alloc(){
int *p1 = malloc(4*sizeof(int));
int *p2 = calloc(4,sizeof(int));
int *p3 = realloc(p2,6*sizeof(int));
// 使用完毕
free(p1);
free(p3);
}
注意:每个 malloc/calloc/realloc
都必须 free
。
嵌入式场景下要考虑碎片化与内存对齐。
本篇(第一部分)完。
下一篇将继续:
递归与回溯
排序进阶(堆排序、归并排序)
常见算法面试题
递归基础:阶乘、斐波那契的尾递、记忆化
回溯进阶:全排列、子集、组合、N 皇后
搜索套路:DFS、BFS 简易框架
电话号码字母组合、word break
词拆分
面试必刷题:括号生成、子集和
// 普通递归
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// 尾递归优化
int factorialTR(int n, int acc) {
if (n <= 1) return acc;
return factorialTR(n - 1, acc * n);
}
void test_factorial() {
printf("factorial(10) = %d\n", factorial(10));
printf("factorialTR(10) = %d\n", factorialTR(10, 1));
}
要点:尾递支持编译器优化为迭代,减少调用栈。
#define MAXN 50
int memo[MAXN];
int fibMemo(int n) {
if (n <= 1) return n;
if (memo[n] != -1) return memo[n];
memo[n] = fibMemo(n-1) + fibMemo(n-2);
return memo[n];
}
void test_fibMemo() {
for (int i = 0; i < 20; i++) memo[i] = -1;
printf("fibMemo(30) = %d\n", fibMemo(30));
}
面试点:避免指数级复杂度。
void swap(char *a, char *b) { char t=*a;*a=*b;*b=t; }
void permute(char *s, int l, int r) {
if (l == r) { printf("%s\n", s); return; }
for (int i = l; i <= r; i++) {
swap(&s[l], &s[i]);
permute(s, l+1, r);
swap(&s[l], &s[i]);
}
}
void subsetDFS(int *arr, int n, int idx, int *buffer, int bsz) {
// 打印当前子集
for (int i = 0; i < bsz; i++) printf("%d ", buffer[i]);
printf("\n");
for (int i = idx; i < n; i++) {
buffer[bsz] = arr[i];
subsetDFS(arr, n, i+1, buffer, bsz+1);
}
}
#define MAXQ 14
int board[MAXQ], totalSolutions;
void solveNQ(int n, int row) {
if (row == n) { totalSolutions++; return; }
for (int col = 0; col < n; col++) {
bool ok = true;
for (int i = 0; i < row; i++) {
if (board[i] == col || abs(board[i]-col)==row-i) { ok=false; break; }
}
if (!ok) continue;
board[row]=col;
solveNQ(n, row+1);
}
}
void dfs(int node, bool *visited) {
visited[node]=true;
// process node
for (int v : adj[node]) {
if (!visited[v]) dfs(v, visited);
}
}
void bfs(int start) {
bool vis[N]={0};
int q[N], head=0, tail=0;
q[tail++]=start; vis[start]=true;
while(head
char *mapArr[]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
void letterComb(char *digits, int idx, char *path, int len) {
if (!digits[idx]) { path[len]='\0'; puts(path); return; }
char *letters=mapArr[digits[idx]-'0'];
for(int i=0;letters[i];i++) {
path[len]=letters[i];
letterComb(digits,idx+1,path,len+1);
}
}
5月20号更新!大家是不是都跟对象约会去了哥们儿没对象所以可以老老实实写代码哈哈哈哈哈哈!!!!
继续:
九 :动态规划问题
动态规划(DP)是将复杂问题分解为子问题,并通过「备忘录」或「状态转移表」记录子问题的最优解,以避免重复计算。其通用五步:
定义状态:明确 dp[i]
或 dp[i][j]
表示什么
初始化:边界条件赋值
状态转移方程:找出子问题之间的关系
遍历顺序:确保子问题先于当前状态计算
结果输出:通常为 dp[n]
或 dp[m-1][n-1]
代码:
// dp_linear.c — 线性动态规划经典题合集 (~667 行)
#include
#include
#include
#include
// 1. 斐波那契数列 — O(n) DP + 滚动数组
int fib_dp(int n) {
if (n < 2) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; i++) {
int c = a + b;
a = b; b = c;
}
return b;
}
void test_fib_dp() {
printf("fib_dp(45) = %d
", fib_dp(45));
}
// 2. 爬楼梯 — DP 等价斐波那契
int climbStairs(int n) {
if (n < 3) return n;
int dp[n+1];
dp[1]=1; dp[2]=2;
for(int i=3;i<=n;i++) dp[i]=dp[i-1]+dp[i-2];
return dp[n];
}
void test_climb() {
printf("climbStairs(10) = %d
", climbStairs(10));
}
// 3. 打家劫舍 I
static int max(int a,int b){return a>b?a:b;}
int rob1(int*nums,int sz){
if(sz==0) return 0;
if(sz==1) return nums[0];
int dp[sz];
dp[0]=nums[0]; dp[1]=max(nums[0],nums[1]);
for(int i=2;ia[j]&&dp[j]+1>dp[i]) dp[i]=dp[j]+1;
if(dp[i]>res)res=dp[i];
}
return res;
}
// 6. 最长上升子序列 O(n log n)
int lengthOfLIS(int*a,int sz){
if(sz==0)return 0;
int*tail=(int*)malloc(sizeof(int)*sz);
int len=1;
tail[0]=a[0];
for(int i=1;i=coins[j]) dp[i]=min(dp[i],dp[i-coins[j]]+1);
}
}
return dp[amount]>amount?-1:dp[amount];
}
void test_coin(){
int c[]={1,2,5};
printf("coinChange= %d
",coinChange(c,3,11));
}
// 9. 不同路径
int uniquePaths(int m,int n){
int dp[m][n];
for(int i=0;i=nums[i];j--)
dp[j]=dp[j]||dp[j-nums[i]];
}
return dp[target];
}
void test_partition(){
int a[]={1,5,11,5};
printf("canPartition= %d
",canPartition(a,4));
}
// 12. 目标和
int findTargetSumWays(int*nums,int sz,int target){
int sum=0;
for(int i=0;i=nums[i];j--) dp[j]+=dp[j-nums[i]];
}
return dp[neg];
}
void test_target(){
int a[]={1,1,1,1,1};
printf("findTargetSumWays= %d
",findTargetSumWays(a,5,3));
}
// main 测试所有线性DP
int main(){
test_fib_dp();
test_climb();
test_rob();
test_lis();
test_lcs();
test_coin();
test_paths();
test_minpath();
test_partition();
test_target();
return 0;
}
代码:
最长回文子串
int longestPalindromeDP(char*s){
int n=strlen(s);
bool dp[n][n]; memset(dp,0,sizeof dp);
int maxLen=1;
for(int i=0;imaxLen) maxLen=L;
}
}
}
return maxLen;
}
区间合并最小成本
int minMergeCost(int *a,int n){
int dp[n][n]; memset(dp,0,sizeof dp);
int sum[n+1]; sum[0]=0;
for(int i=0;i
1代码:
int selectActivity(int start[],int end[],int n){
int count=0, lastEnd=0;
// 以 end 升序排序
for(int i=0;i=lastEnd){ count++; lastEnd=end[i]; }
}
return count;
}
给定一组活动,其开始时间和结束时间分别存储在数组 start[]
和 end[]
中,要求选择互不重叠的最大活动数量。
贪心选择:每次优先选择结束最早的活动,以腾出更多时间给后续活动。
实现步骤:
a. 将活动按结束时间升序排序;
b. 维护当前已选活动的结束时间 lastEnd
;
c. 遍历排序后活动列表,若 start[i] >= lastEnd
,则选取该活动,并更新 lastEnd = end[i]
。
#include
#include
// 活动结构体
typedef struct {
int start;
int end;
} Activity;
// 用于 qsort 的比较函数:按结束时间升序
int cmpActivity(const void *a, const void *b) {
Activity *x = (Activity*)a;
Activity *y = (Activity*)b;
return x->end - y->end;
}
// 区间调度:返回最大可选活动数量
int intervalScheduling(Activity *acts, int n) {
// 1. 按结束时间排序
qsort(acts, n, sizeof(Activity), cmpActivity);
// 2. 选择活动
int count = 0;
int lastEnd = -1; // 初始化为最早时间之前
for (int i = 0; i < n; i++) {
if (acts[i].start >= lastEnd) {
count++;
lastEnd = acts[i].end;
}
}
return count;
}
// 测试函数
void test_interval_scheduling() {
Activity acts[] = {
{1, 4}, {3, 5}, {0, 6}, {5, 7},
{3, 9}, {5, 9}, {6, 10}, {8, 11},
{8, 12}, {2, 14}, {12, 16}
};
int n = sizeof(acts) / sizeof(Activity);
int result = intervalScheduling(acts, n);
printf("Maximum number of non-overlapping activities = %d
", result);
}
// main 中调用测试
int main() {
test_interval_scheduling();
return 0;
}
给定两个字符串 s
和 t
,在 s
中找到包含 t
所有字符的最小子串,返回该子串;若不存在则返回空字符串。
滑动窗口框架:使用左右指针 L
,R
定义窗口,初始都为0。
需求计数:使用哈希表 need[256]
记录 t
中每字符所需个数,window[256]
记录当前窗口中字符出现个数。
扩展窗口:移动 R
,更新 window
,并在满足所有需求时,尝试收缩窗口。
收缩窗口:移动 L
,在满足条件的前提下更新最小窗口长度,并更新 window
。若不再满足,则跳出收缩,继续扩展。
#include
#include
#include
// 返回最小覆盖子串的起始索引与长度
void minWindowSubstring(const char *s, const char *t, int *start, int *len) {
int need[256] = {0}, window[256] = {0};
int required = 0;
for (int i = 0; t[i]; i++) {
if (need[(unsigned char)t[i]] == 0) required++;
need[(unsigned char)t[i]]++;
}
int L = 0, R = 0, valid = 0;
int minLen = INT_MAX, minStart = 0;
int slen = strlen(s);
while (R < slen) {
char c = s[R++];
// 更新窗口数据
if (need[(unsigned char)c] > 0) {
window[(unsigned char)c]++;
if (window[(unsigned char)c] == need[(unsigned char)c]) valid++;
}
// 当所有需求字符都已满足,尝试收缩窗口
while (valid == required) {
// 更新最小窗口
if (R - L < minLen) {
minLen = R - L;
minStart = L;
}
char d = s[L++];
if (need[(unsigned char)d] > 0) {
if (window[(unsigned char)d] == need[(unsigned char)d]) valid--;
window[(unsigned char)d]--;
}
}
}
if (minLen == INT_MAX) {
*start = 0; *len = 0;
} else {
*start = minStart;
*len = minLen;
}
}
void test_minWindow() {
const char *s = "ADOBECODEBANC";
const char *t = "ABC";
int start, length;
minWindowSubstring(s, t, &start, &length);
if (length > 0)
printf("Min window: %.*s
", length, s + start);
else
printf("No valid window
");
}
给定一个整数数组 nums
,找出所有不重复的三元组 [a,b,c]
,使得 a+b+c = 0
。
排序:对数组升序排序,便于双指针跳过重复值。
固定一位:使用索引 i
遍历,每次固定 nums[i]
,目标和为 -nums[i]
。
双指针:在 i+1..n-1
区间,设置 L=i+1
, R=n-1
,若 nums[L]+nums[R]
大于目标,R--
;小于目标,L++
;等于时记录答案并双指针同时收缩,同时跳过重复元素。
代码:
#include
#include
#include
// 比较函数
int cmpInt(const void*a,const void*b){return *(int*)a-*(int*)b;}
// 打印三元组
void printTriplet(int a,int b,int c){
printf("[%d, %d, %d]
", a, b, c);
}
void threeSum(int* nums, int sz) {
qsort(nums, sz, sizeof(int), cmpInt);
for(int i = 0; i < sz - 2; i++) {
if (i > 0 && nums[i] == nums[i-1]) continue; // 跳过重复
int target = -nums[i];
int L = i+1, R = sz-1;
while (L < R) {
int sum = nums[L] + nums[R];
if (sum < target) {
L++;
} else if (sum > target) {
R--;
} else {
printTriplet(nums[i], nums[L], nums[R]);
// 跳过重复
while (L < R && nums[L] == nums[L+1]) L++;
while (L < R && nums[R] == nums[R-1]) R--;
L++; R--;
}
}
}
}
void test_threeSum() {
int a[] = {-1,0,1,2,-1,-4};
printf("3Sum results:
");
threeSum(a, 6);
}
给定字符串 s
,找出其中不含重复字符的最长子串的长度。
滑动窗口 + 哈希表:同最小覆盖子串的框架,但这里维护窗口中每字符最后出现位置 index[256]
。
动态更新左边界:当遇到重复字符 c
时,将左边界 L
更新为 max(L, index[c]+1)
。
计算最大长度:每次扩展窗口时更新 maxLen = max(maxLen, R-L+1)
。
代码:
#include
#include
int lengthOfLongestSubstring(char *s) {
int index[256];
for(int i=0;i<256;i++) index[i] = -1;
int L = 0, maxLen = 0;
for (int R = 0; s[R]; R++) {
unsigned char c = s[R];
if (index[c] >= L) {
L = index[c] + 1;
}
index[c] = R;
int currLen = R - L + 1;
if (currLen > maxLen) maxLen = currLen;
}
return maxLen;
}
void test_longestSubstr() {
char *s = "abcabcbb";
printf("Longest substring length = %d
", lengthOfLongestSubstring(s));
}
#include
#include
#include
#include
#include
#include
// 测试数据类型的大小和范围
void testDataTypeRange() {
// 字符类型
printf("===== 字符类型 =====\n");
printf("char 大小: %zu 字节\n", sizeof(char));
printf("char 最小值: %d\n", (int)CHAR_MIN);
printf("char 最大值: %d\n", (int)CHAR_MAX);
// 短整型
printf("\n===== 短整型 =====\n");
printf("short 大小: %zu 字节\n", sizeof(short));
printf("short 最小值: %d\n", SHRT_MIN);
printf("short 最大值: %d\n", SHRT_MAX);
// 整型
printf("\n===== 整型 =====\n");
printf("int 大小: %zu 字节\n", sizeof(int));
printf("int 最小值: %d\n", INT_MIN);
printf("int 最大值: %d\n", INT_MAX);
// 长整型
printf("\n===== 长整型 =====\n");
printf("long 大小: %zu 字节\n", sizeof(long));
printf("long 最小值: %ld\n", (long)LONG_MIN);
printf("long 最大值: %ld\n", (long)LONG_MAX);
// 长长整型
printf("\n===== 长长整型 =====\n");
printf("long long 大小: %zu 字节\n", sizeof(long long));
printf("long long 最小值: %lld\n", (long long)LLONG_MIN);
printf("long long 最大?: %lld\n", (long long)LLONG_MAX);
// 固定宽度整数类型
printf("\n===== 固定宽度整数类型 =====\n");
#if defined(__INT32_T__)
printf("int32_t 存在,大小: %zu 字节\n", sizeof(int32_t));
#else
printf("int32_t 不存在,编译器可能不支持\n");
#endif
}
// 测试printf函数的各种格式化输出
void testPrintfFormat() {
int integerValue = 234;
float floatValue = 9.8f;
char charValue = '@';
char str[] = "C Language";
printf("\n\n===== 1. 字段对齐方式(右/左对齐) =====\n");
printf("%10d\n", integerValue); // 右对齐,宽度10(默认空格填充)
printf("%-22.24f\n", floatValue); // 左对齐,宽度22(-表示左对齐)
printf("%10c\n", charValue); // 字符右对齐,宽度4
printf("%8s\n", str); // 字符串右对齐,宽度8
printf("\n");
int number = 123456;
double doubleValue = 882.123456789123456789123456789123456789;
char* longStr = "abcdefghi";
printf("===== 2. 宽度控制(整数、小数位数、字符串截取) =====\n");
printf("整数前补零:%.15d %.4d\n", number, number); // 宽度控制,整数位数
printf("小数位数:%.2lf %.4lf %.100lf\n",
doubleValue, doubleValue, doubleValue); // 小数位数
printf("字符串截取:%4s %.8s\n", longStr, longStr); // 截取前4/8个字符,4位不够用空格补齐
printf("\n");
int year = 1977;
printf("===== 3. 填充与符号显示 =====\n");
printf("空格填充(右对齐)\n%-10d -%10d\n", year, year); // 宽度10,空格填充
printf("零填充:%-110d\n", year); // 宽度10,零填充
printf("强制显示符号:%+.2f %+.0e\n", 3.14, 3.14); // 显示正负号
printf("\n");
int decimal = 100;
printf("===== 4. 进制转换 =====\n");
printf("十进制:%d\n", decimal); // 十进制
printf("十六进制:小写字母%x 带前缀%#x\n", decimal, decimal); // 十六进制
printf("八进制:大写字母%O 带前缀%#o\n", decimal, decimal); // 八进制,%O为大写八进制
printf("\n");
printf("===== 5. 综合示例 =====\n");
printf("指针地址:%p\n", (&integerValue)); // 指针地址,%p格式
printf("科学计数法:%.40E\n", 3.1415926123456789); // 高精度科学计数法
printf("字符串输出:%s\n", "C语言格式化输出示例"); // 普通字符串输出
printf("\n");
}
// 测试浮点数的比较
void testFloatComparison() {
float a = -3.11131923487;
float anew = fabs(a);
printf("anew (float): %50f\n", anew); // 注意使用%f输出float
double x1 = 123.123456789;
double x2 = 123.123456789;
printf("\n\nx1-x2的值:%.50lf\n\n", fabs(x1 - x2));
double a2 = 1.1;
double b2 = 1.0;
double c2 = fabs(a2 - b2) - 0.1;
printf("c2 = %.50lf\n", c2); // 输出50位小数
// 实际结果c2 = 0.0000000000000000555111512312578270211815834045
printf("c2 = %.50lf\n", c2); // 输出20位小数查看结果
const double eps = 1e-9; // 定义极小值
if (fabs(c2 - 0.00000001) < eps)
{
printf("c2 约等于 0.00000001\n");
}
else
{
printf("c2 不等于 0.00000001\n");
printf("实际 c2 的值:%.57e\n", c2); // 科学计数法表示实际值
}
}
// 测试数组相关操作
void testArray() {
// 一维数组初始化
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {1, 2, 3}; // 自动补0
int arr3[] = {1, 3, 4, 5, 6}; // 自动计算长度
printf("一维数组初始化示例:\n");
for (int i = 0; i < 5; i++) {
printf("arr1[%d]=%d, arr2[%d]=%d, arr3[%d]=%d\n",
i, arr1[i], i, arr2[i], i, arr3[i]);
}
// 数组越界示例(注意:实际编程中应避免)
int arr[6] = {1, 2, 3, 4, 5, 6};
printf("越界示例(危险,请勿在实际中使用):\n");
for (int i = 0; i <= 8; i++) { // 注意:这里会访问arr[6],发生越界
printf("arr[%d]=%d\n", i, arr[i]);
}
// 二维数组示例
int arr2D[2][3] = {{12, 3, 4}, {12, 22, 33}};
printf("\n二维数组示例:\n");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("arr2D[%d][%d]=%d\t", i, j, arr2D[i][j]);
}
printf("\n");
}
// 数组作为参数传递
int arrParam[] = {1, 3, 5, 7, 9};
printf("\n数组作为参数传递:\n");
for (int i = 0; i < 5; i++) {
printf("arrParam[%d]=%d\n", i, arrParam[i]);
}
// 排序算法
int sortArr[] = {5, 3, 8, 4, 2};
int size = sizeof(sortArr) / sizeof(sortArr[0]);
printf("\n选择排序前:\n");
for (int i = 0; i < size; i++) {
printf("sortArr[%d]=%d\n", i, sortArr[i]);
}
// 选择排序
for (int i = 0; i < size - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < size; j++) {
if (sortArr[j] < sortArr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = sortArr[i];
sortArr[i] = sortArr[minIndex];
sortArr[minIndex] = temp;
}
}
printf("\n选择排序后:\n");
for (int i = 0; i < size; i++) {
printf("sortArr[%d]=%d\n", i, sortArr[i]);
}
// 数组反转
printf("\n数组反转前:\n");
for (int i = 0; i < size; i++) {
printf("%d ", sortArr[i]);
}
int start = 0;
int end = size - 1;
while (start < end) {
int temp = sortArr[start];
sortArr[start] = sortArr[end];
sortArr[end] = temp;
start++;
end--;
}
printf("\n数组反转后:\n");
for (int i = 0; i < size; i++) {
printf("%d ", sortArr[i]);
}
printf("\n");
}
// 测试运算符
void testOperators() {
int a = 4;
int b = 5;
a *= b + 1;
printf("%d\n ", a);
unsigned char c = 0x17;
unsigned char d = ~c;
printf("%#x\n", d);
int x = 10;
int y = 20;
x = x ^ y;
y = x ^ y;
x = x ^ y;
printf("%d %d\n", x, y);
int a1 = 12;
int a2;
a2 = 10 < a1 && a1 > 1;
printf("ret = %d \n", a2);
}
// 测试类型转换
void testTypeConversion() {
int a = 3.14;
double b = 0.1;
printf("%d\n", a);
printf("%.30f\n", b);
char char1 = 'A';
int int1 = 1000;
printf("%c\n", char1 + int1);
printf("%d\n", char1 + int1);
int a2 = 100;
int b2 = 3;
float c2 = a2 / (float)b2;
printf("%.30lf\n", c2);
int former = 100;
former <<= 1;
printf("%d\n", former);
former >>= 17;
printf("%d\n", former);
}
// 测试控制结构
void testControlStructures() {
// if-else语句
int age = 25; // 预设年龄
printf("请输入年龄 (预设值: %d):\n", age);
// scanf("%d", &age);
if (age >= 18) {
printf("成年人\n");
} else if (age >= 6) {
printf("儿童6岁以上\n");
} else if (age >= 3) {
printf("小孩 3岁以上\n");
} else {
printf("婴儿\n");
}
// switch语句
int year = 2024, month = 2, days;
printf("请输入年份和月份(格式:YYYY-MM)(预设值: %d-%d):\n", year, month);
// scanf("%d-%d", &year, &month);
switch (month) {
case 1:
days = 31;
printf("一月\n");
break;
case 2:
if ((year % 100 != 0 && year % 4 == 0) || (year % 400 == 0)) {
days = 29;
} else {
days = 28;
}
break;
case 3:
days = 31;
break;
case 4:
days = 30;
break;
case 5:
days = 31;
break;
case 6:
days = 30;
break;
case 7:
days = 31;
break;
case 8:
days = 31;
break;
case 9:
days = 30;
break;
case 10:
days = 31;
break;
case 11:
days = 30;
break;
default:
days = 12;
break;
}
printf("该月有%d天\n", days);
// for循环
long long a = 2;
for (long long i = 1; i < 30; i++) { // 修改循环条件以防止溢出
a = a * i;
printf("%lld次后,a的值为:%lld\n", i, a);
if (a < 0) { // 检查是否溢出
printf("检测到溢出,停止计算。\n");
break;
}
}
int m = 5; // 预设m值
printf("请输入一个整数m (预设值: %d):\n", m);
// scanf("%d", &m);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < m; j++) {
printf("*");
}
printf("--\n\n--");
}
}
// 测试bool类型
void testBoolType() {
bool a = -1;
bool b = 0;
bool c = 1;
bool d = -1000000000;
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
printf("%d\n", d);
}
int main() {
testDataTypeRange();
testPrintfFormat();
testFloatComparison();
testArray();
testOperators();
testTypeConversion();
testControlStructures();
testBoolType();
return 0;
}
// #self init statement
// 这里说明清楚:原来的代码有五百行
// 自己根据AI和华清园圈的课程写的现在底薪的一部分是AI重新给我优化生成的但是
// 之前写的我也不会给他删掉做一个备份?
// #include
// #include
// #include
// #include
// // 指针访问数组中的元素
// void arr1_ptr()
// {
// int arr[] = {1, 2, 4, 5, 6, 56, 67, 8, 9};
// int *ptr = arr;
// int len = sizeof(arr) / sizeof(arr[0]);
// for (int i = 0; i < len; i++)
// {
// printf("指针访问:%d,数组访问:%d\n ", *(ptr + i), arr[i]);
// }
// }
// // 转置操作
// // #self 数组没办法获取数组大小 :sizeof(arr)这个会失效!!!
// void zhuanzhi(int arr[3][3])
// {
// for (int i = 0; i < 3; i++)
// {
// for (int j = i + 1; j < 3; j++)
// {
// int temp = arr[i][j];
// arr[i][j] = arr[j][i];
// arr[j][i] = temp;
// }
// }
// }
// static void dy_alloc_mem()
// {
// int *arr1 = (int *)malloc(1000000 * sizeof(int));
// if (arr1 == NULL)
// {
// printf("内存分配失败!\n");
// return;
// }
// for (int i = 0; i < 1000000; i++)
// {
// *(arr1 + i) = i;
// }
// // 时间戳1
// clock_t start, end;
// start = clock();
// int i;
// for (i = 0; i < 100; i++)
// {
// printf("%d \n", *(arr1 + i));
// }
// end = clock();
// double t = (double)(end - start);
// printf("打印这些%d用了%10f毫秒\n", i, t);
// //
// // 时间戳2
// }
// void string_reverse(char *str, int len)
// {
// char *start = str;
// char *end = start + len - 1;
// while (start < end)
// {
// char temp = *start;
// *start = *end;
// *end = temp;
// start++;
// end--;
// }
// }
// int add(int a, int b)
// {
// return a + b;
// }
// int substract(int a, int b)
// {
// return a - b;
// }
// struct Person
// {
// char name[10];
// int age;
// };
// struct Node
// {
// int data;
// struct Node *next;
// };
// struct Node *insert_atFirst(struct Node *head, int data)
// {
// // self
// // vip!!!
// // 在末尾插入!
// struct Node *n_node = (struct Node *)malloc(sizeof(struct Node));
// n_node->data = data;
// n_node->next = head;
// return n_node;
// }
// void print_List(struct Node *node)
// {
// struct Node *l = node;
// while (l != NULL)
// {
// printf("这是打印的节点:!!! %d \n", l->data);
// l = l->next;
// }
// return;
// }
// void swap(int *a, int *b)
// {
// int temp = *a;
// *a = *b;
// *b = temp;
// }
// int cnt11 = 0;
// int partition(int arr[], int low, int high)
// {
// int pi = arr[high];
// int i = low - 1;
// for (int j = low; j <= high - 1; j++)
// {
// if (arr[j] <= pi)
// {
// i++;
// swap(&arr[i], &arr[j]);
// }
// }
// swap(&arr[i + 1], &arr[high]);
// printf("\n\n---现在是partition%d次调用\n,pi是%d\n", cnt11++, pi);
// for (int i = 0; i < high; i++)
// {
// printf(" %d-", arr[i]);
// }
// printf("---现在是partition%d次调用\n\n", cnt11++);
// return i + 1;
// }
// void quick_Sort(int arr[], int low, int high)
// {
// if (low < high)
// {
// int pi = partition(arr, low, high);
// quick_Sort(arr, low, pi - 1);
// quick_Sort(arr, pi + 1, high);
// }
// }
// struct Address{
// char street[50];
// int house_number;
// };
// struct Person_16{
// char name[20];
// struct Address address;
// };
// void Print_address(struct Person_16* p){
// printf("%s \n",p->name);
// printf("%s \n",p->address.street);
// printf("%d \n",p->address.house_number);
// }
// //#self vip !!!!
// //不自己写 根本就不知道有这么多不懂的内容!
// void connect_char(char* a,char* b){
// char* p1 = a + strlen(a);
// printf("这是实验18里面的callback,a的长度是:%d ,b的长度是:%d\n",strlen(a),strlen(b));
// // for(int i=0;itop=-1;
// }
// int isEmpty(struct stack* s ){
// if(s->top==-1){
// return 1;
// }
// else{
// return -100;
// }
// }
// int isFull(struct stack* s ){
// if(s->top==maxL){
// return 1;
// }
// else{
// return 0;
// }
// }
// void pushStack(struct stack* s ,int data ){
// //判断栈是不是满了?
// if(s->top==maxL){
// return ;
// }
// else{
// s->data[++(s->top)] = data;
// }
// }
// int popStack(struct stack* s ){
// //判断是不是空?空了就返回-1
// if(isEmpty(s)){
// return -1;
// }
// else{
// int res = s->data[s->top--];
// }
// }
// int peekTop(struct stack* s ){
// return s->data[s->top];
// }
// int main()
// {
// // 访问数组元素
// // arr1_ptr();
// // printf("1 访问数组元素结束!\n");
// // // 多维数组的内存布局
// // // 把一个二维数组转置操作一下
// // // #self 数组没办法获取数组大小 :sizeof(arr)这个会失效!!!
// // int arr[3][3] = {
// // {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// // zhuanzhi(arr);
// // for (int i = 0; i < 3; i++)
// // {
// // for (int j = 0; j < 3; j++)
// // {
// // printf("%d ", arr[i][j]);
// // }
// // printf("\n");
// // }
// // printf("\n\n实验转置操作\n");
// // // 动态分配内存打印
// // printf("第3实验开始!\n");
// // dy_alloc_mem();
// // printf("第3实验结束!\n");
// // printf("\n\n第四个实验开始\n\n");
// // char charS[100] = {'0', '1', '2', '3', '4', '5', '\0'};
// // int char_len = strlen(charS);
// // printf("这个字符数组的长度:%d \n", char_len);
// // printf("但是强行从0-100打印就是:\n");
// // for (int i = 0; i < 5; i++)
// // {
// // printf("%c \n", charS[i]);
// // }
// // string_reverse(charS, char_len);
// // for (int i = 0; i < char_len; i++)
// // {
// // printf("%c \n", charS[i]);
// // }
// // printf("第4个实验结束\n\n");
// // // 第5个实验:函数指针
// // // 手动实现一个计算器
// // printf("\n第5个实验开始\n\n");
// // int a = 100, b = 50;
// // int (*func_ptr)(int a, int b);
// // printf("告诉我你要的操作:\n");
// // char op;
// // scanf("%c", &op);
// // switch (op)
// // {
// // case '+':
// // func_ptr = add;
// // {
// // int res = func_ptr(a, b);
// // printf("%d\n", res);
// // break;
// // }
// // case '-':
// // func_ptr = substract;
// // {
// // int res = func_ptr(a, b);
// // printf("%d\n", res);
// // break;
// // }
// // }
// // printf("\n第5个实验结束\n\n");
// // printf("\n第六个实验,二维数组动态分配\n");
// // int m =3,n =4 ;
// // int **arr_6 =(int**)malloc(m*sizeof(int*));
// // for(int i= 0;iname, "jibamao");
// // p->name = "jibamao";
// printf("改过之后:%s\n", p->name);
// // #self vip!
// // 结构体指针的作用
// // #self
// // 实验9 链表节点的插入
// printf("\n\n实验9 链表的插入\n");
// struct Node *head_node = NULL;
// // struct Node node = {123,NULL};
// head_node = insert_atFirst(head_node, 123);
// printf("\n第一个节点:%d\n ", head_node->data);
// head_node = insert_atFirst(head_node, 4);
// printf("\n第二个节点 : %d\n", head_node->data);
// print_List(head_node);
// // #self vip!!!
// // 实验10 冒泡排序优化
// printf("实验10 冒泡排序优化!\n");
// // 11 快排法
// // #self vip!!!
// printf("\n\n实验11 快速排序!!开始!!!\n");
// int arr11[] = {4, 5, 6, 7, 15, 234, 46, 698, 238, 258, 45, 2, 36, 26, 123, 77, 5, 48, 45, 2, 5, 325, 32, 1, 6};
// int len = sizeof(arr11) / sizeof(arr11[0]);
// quick_Sort(arr11, 0, len - 1);
// for (int i = 0; i < len; i++)
// {
// printf("快排打印的结果是");
// printf("%d\n", arr11[i]);
// }
// printf("\n\n实验11 快排结束!!!\n");
// // 13实验 文件读写操作
// //
// // 14整数阶乘
// // 15指针数组与二维数组区别:
// // #self vip
// printf("\n\n实验15开始 \n\n");
// char *str15[] = {"ab", "123", "efg", "jkl"};
// char str15new[3][10] = {"baname", "apple", "milk"};
// int len1 = sizeof(strlen(str15))/sizeof(str15[0]);
// for (int i = 0; i
#include
#include
#include
// 指针数组、结构体指针、链表插入、快排、栈
int cnt11 = 0;
// ====================== 提前结构体定义 ======================
struct Person
{
char name[10];
int age;
};
struct Node
{
int data;
struct Node *next;
};
#define maxL 100
struct stack
{
int data[maxL];
int top;
};
// ====================== 函数前置声明 ======================
void arr1_ptr();
void zhuanzhi(int arr[3][3]);
static void dy_alloc_mem();
void string_reverse(char *str, int len);
int add(int a, int b);
int substract(int a, int b);
struct Node *insert_atFirst(struct Node *head, int data);
void print_List(struct Node *node);
void swap(int *a, int *b);
int partition(int arr[], int low, int high);
void quick_Sort(int arr[], int low, int high);
void connect_char(char *a, char *b);
void initStack(struct stack *s);
int isEmpty(struct stack *s);
int isFull(struct stack *s);
void pushStack(struct stack *s, int data);
int popStack(struct stack *s);
int peekTop(struct stack *s);
// ====================== 原始函数实现 ======================
// 指针访问数组中的元素
void arr1_ptr()
{
int arr[] = {1, 2, 4, 5, 6, 56, 67, 8, 9};
int *ptr = arr;
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++)
{
printf("指针访问:%d,数组访问:%d\n ", *(ptr + i), arr[i]);
}
}
// 转置操作
void zhuanzhi(int arr[3][3])
{
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
}
static void dy_alloc_mem()
{
int *arr1 = (int *)malloc(1000000 * sizeof(int));
if (arr1 == NULL)
{
printf("内存分配失败!\n");
return;
}
for (int i = 0; i < 1000000; i++)
{
*(arr1 + i) = i;
}
clock_t start, end;
start = clock();
int i;
for (i = 0; i < 100; i++)
{
printf("%d \n", *(arr1 + i));
}
end = clock();
double t = (double)(end - start);
printf("打印这些%d用了%10f毫秒\n", i, t);
}
void string_reverse(char *str, int len)
{
char *start = str;
char *end = start + len - 1;
while (start < end)
{
char temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}
int add(int a, int b)
{
return a + b;
}
int substract(int a, int b)
{
return a - b;
}
struct Node *insert_atFirst(struct Node *head, int data)
{
struct Node *n_node = (struct Node *)malloc(sizeof(struct Node));
n_node->data = data;
n_node->next = head;
return n_node;
}
void print_List(struct Node *node)
{
struct Node *l = node;
while (l != NULL)
{
printf("这是打印的节点:!!! %d \n", l->data);
l = l->next;
}
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int partition(int arr[], int low, int high)
{
int pi = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; j++)
{
if (arr[j] <= pi)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
printf("\n\n---现在是partition%d次调用\n,pi是%d\n", cnt11++, pi);
for (int i = 0; i < high; i++)
{
printf(" %d-", arr[i]);
}
printf("---现在是partition%d次调用\n\n", cnt11++);
return i + 1;
}
void quick_Sort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quick_Sort(arr, low, pi - 1);
quick_Sort(arr, pi + 1, high);
}
}
void connect_char(char *a, char *b)
{
char *p1 = a + strlen(a);
printf("这是实验18里面的callback,a的长度是:%d ,b的长度是:%d\n", strlen(a), strlen(b));
while (*b != '\0')
{
*p1 = *b;
p1++;
b++;
}
*p1 = '\0';
}
void initStack(struct stack *s)
{
s->top = -1;
}
int isEmpty(struct stack *s)
{
if (s->top == -1)
{
return 1;
}
else
{
return -100;
}
}
int isFull(struct stack *s)
{
if (s->top == maxL)
{ // 注意:这里可能存在越界风险,原始逻辑未修正
return 1;
}
else
{
return 0;
}
}
void pushStack(struct stack *s, int data)
{
if (s->top == maxL)
{
return;
}
else
{
s->data[++(s->top)] = data;
}
}
int popStack(struct stack *s)
{
if (isEmpty(s))
{
return -1;
}
else
{
int res = s->data[s->top--];
return res; // 原始代码遗漏return
}
}
int peekTop(struct stack *s)
{
return s->data[s->top];
}
// 指针数组、结构体指针、链表插入、快排、栈
// ====================== 主函数 ======================
int main()
{
// 实验7 指针数组用法
printf("实验7 指针数组用法\n");
char *string[] = {"qibamao", "abc", "123", "why", "你是神秘嘉宾", "\0"};
int len7 = sizeof(string) / sizeof(string[0]);
for (int i = 0; i < len7; i++)
{
printf("%s\n", string[i]);
}
char string7[] = "123123";
printf("%d\n", sizeof(string7));
for (int i = 0; i < sizeof(string7); i++)
{
printf("%c", string7[i]);
}
// 结构体指针实验
struct Person person = {"xiaomin", 18};
printf("\n%s-%d\n", person.name, person.age);
struct Person *p = &person;
strcpy(p->name, "jibamao");
printf("改过之后:%s\n", p->name);
// 链表实验
printf("\n\n实验9 链表的插入\n");
struct Node *head_node = NULL;
head_node = insert_atFirst(head_node, 123);
printf("\n第一个节点:%d\n ", head_node->data);
head_node = insert_atFirst(head_node, 4);
printf("\n第二个节点 : %d\n", head_node->data);
print_List(head_node);
// 快速排序实验
printf("\n\n实验11 快速排序!!开始!!!\n");
int arr11[] = {4, 5, 6, 7, 15, 234, 46, 698, 238, 258, 45, 2, 36, 26, 123, 77, 5, 48, 45, 2, 5, 325, 32, 1, 6};
int len = sizeof(arr11) / sizeof(arr11[0]);
quick_Sort(arr11, 0, len - 1);
for (int i = 0; i < len; i++)
{
printf("快排打印的结果是%d\n", arr11[i]);
}
// 栈结构实验
struct stack s;
initStack(&s);
printf("\n初始了,是不是空?%d\n", isEmpty(&s));
pushStack(&s, 1);
printf("插入了1,是不是空?%d\n", isEmpty(&s));
pushStack(&s, 2);
pushStack(&s, 3);
printf("栈顶是:%d\n", peekTop(&s));
pushStack(&s, 4);
printf("栈顶是:%d\n", peekTop(&s));
popStack(&s);
printf("弹出后栈顶是:%d\n", peekTop(&s));
return 0;
}
#include
#include
// 转置 动态分配内存、k大算法->脱胎与快排法
// 转置矩阵函数
void zhuanzhi()
{
// 定义并初始化一个3x3的矩阵
int a[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// 输出原始矩阵
printf("原始矩阵:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
// 转置矩阵
printf("现在开始转置:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < i; j++)
{
int temp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp;
}
}
// 输出转置后的矩阵
printf("转置之后:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}
// 动态分配一维数组函数
int *alloc_1dArr()
{
// 分配100个整数的内存空间
int *arr = (int *)malloc(100 * sizeof(int));
// 初始化数组元素
for (int i = 0; i < 100; i++)
{
arr[i] = i;
}
return arr;
}
// 动态分配二维数组函数
int **alloc_2dArr(int row, int col)
{
// 分配row个指针的内存空间,用于存储每一行的地址
int **a1 = (int **)malloc(row * sizeof(int *));
// 为每一行分配col个整数的内存空间,并初始化元素
for (int i = 0; i < row; i++)
{
a1[i] = (int *)malloc(col * sizeof(int));
for (int j = 0; j < col; j++)
{
a1[i][j] = i * col + j;
}
}
// 输出二维数组
printf("动态分配的二维数组:\n");
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%4d ", a1[i][j]);
}
printf("\n");
}
return a1;
}
// 交换两个整数的函数
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// 分区函数(移除冗余的k参数)
int partition(int a[], int left, int right)
{
int pivot = a[right]; // 选择最右元素作为枢轴
int i = left - 1; // 标记大于枢轴区域的末尾
for (int j = left; j <= right - 1; j++)
{
if (a[j] > pivot)
{ // 降序分区:左侧元素 > 枢轴
i++; // 扩大左侧区域
swap(&a[i], &a[j]); // 交换到正确位置
}
}
swap(&a[i + 1], &a[right]); // 枢轴归位
return i + 1; // 返回枢轴索引(第rank大元素的位置)
}
// 查找第k大元素函数
int findKthlarge(int a[], int left, int right, int k)
{
if (left == right)
return a[left];
int pivot = partition(a, left, right);
int rank = pivot - left + 1; // 计算枢轴排名
if (rank == k)
{ // 找到第k大
return a[pivot];
}
else if (rank > k)
{ // 左半部分查找
return findKthlarge(a, left, pivot - 1, k);
}
else
{ // 右半部分查找,调整k
return findKthlarge(a, pivot + 1, right, k - rank);
}
}
int main(void)
{
// 标记当前是实验1
printf("实验1:矩阵转置\n");
zhuanzhi();
// 标记当前是实验2
printf("\n实验2:动态分配一维数组\n");
int *a1 = alloc_1dArr();
for (int i = 0; i < 100; i++)
{
printf("%d ", a1[i]);
}
printf("\n");
// 标记当前是实验3
printf("\n实验3:动态分配二维数组\n");
int m = 10, n = 15;
int **a2 = alloc_2dArr(m, n);
// 标记当前是实验4
printf("\n实验4:找到第k大的数字\n");
int arr4[] = {34, 78, 12, 56, 89, 23, 45, 67, 90, 11};
int len4 = sizeof(arr4) / sizeof(arr4[0]);
printf("这里的arr4的长度是:%d\n", len4);
int k = 8;
int res4 = findKthlarge(arr4, 0, len4 - 1, k);
printf("数组arr4的元素:\n");
for (int i = 0; i < len4; i++)
{
printf("%d ", arr4[i]);
}
printf("\n第k大(第4大)的数字就是:%d\n\n", res4);
// 实验5:指针遍历二维数组
// 这里可以添加一个新的函数来演示指针遍历二维数组
// 实验6
// 实验7
return 0;
}
#include
#include
#include
// D9:多级指针、void指针、const
typedef struct Node
{
int value;
struct Node **children; // #self 多级指针:指向结构体指针的数组
int child_count;
} Node;
void add_child(Node *parent, Node *child)
{
// realloc函数,动态扩展函数 !!!vip 节省空间 #self
parent->children = realloc(parent->children, (parent->child_count + 1) * sizeof(Node *)); // #self vip 动态扩展二级指针数组
parent->children[parent->child_count++] = child;
}
void *arrtoPtrInt(void *x)
{ // #self vip void指针通用类型转换
return (char *)(x) + 2; // #self 指针运算:char*偏移2字节
}
// D10:函数的基本用法及传参
void printArr(int arr[], int len)
{ // #self 数组传参退化为指针
for (int i = 0; i < len; i++)
printf("元素%d的值: %d\n", i, arr[i]);
}
// D11:函数的传参 #self vip!!! 对字符串数组的序列排序 a1
void arrSort(char *arr[], int n)
{ // #self 指针数组排序:字符指针比较
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - 1 - i; j++)
if (strcmp(arr[j], arr[j + 1]) > 0)
{
char *temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// D12:指针函数
int *dy_alloc(int n)
{ // #self vip 指针函数返回动态数组
int *res = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
res[i] = i;
return res;
}
// D14:#define和typedef #self 宏定义 !!!vip
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) // #self 宏定义计算数组长度
// D15:变量的作用域和生命周期
// (原代码未体现,保留为示例位置)
// D16:字符串处理函数 #self 字符串长度函数!
int getStrLen(char *a)
{ // #self 字符指针遍历
char *p = a;
while (*p != '\0')
p++;
return p - a; // #self 指针差值计算长度
}
char *strCpyFn(char *dest, char *src)
{ // #self 指针函数:返回目标字符串指针
char *result = dest;
while (*src)
*dest++ = *src++;
*dest = '\0';
return result;
}
int main()
{
// D9:多级指针测试
Node root = {1, NULL, 0};
Node child1 = {2, NULL, 0};
add_child(&root, &child1); // #self 多级指针添加子节点
printf("节点%d的子节点值: %d\n", root.value, root.children[0]->value);
// D9:void指针测试
char arr[] = {'a', 'b', 'c', 'd'};
char *ptr = arrtoPtrInt(arr);
printf("void指针偏移后的值: %c\n", *ptr);
// D10:函数传参测试
int arr1[] = {1, 2, 3, 4, 5};
printArr(arr1, ARRAY_LEN(arr1)); // #self 使用宏定义计算数组长度
// D11:指针数组排序
char *arr6[] = {"apple", "banana", "cherry"};
arrSort(arr6, 3);
printf("排序后的字符串: %s, %s, %s\n", arr6[0], arr6[1], arr6[2]);
// D12:指针函数测试
int *dyn_arr = dy_alloc(5);
printf("动态分配数组: %d, %d, %d, %d, %d\n", dyn_arr[0], dyn_arr[1], dyn_arr[2], dyn_arr[3], dyn_arr[4]);
free(dyn_arr);
// D16:字符串处理测试
char src[] = "Hello";
char dest[10];
strCpyFn(dest, src);
printf("字符串拷贝结果: %s (长度: %d)\n", dest, getStrLen(dest));
// #self ai分析 !!!vip 进度:截至25年5月20号
/* 目录逻辑:基础→指针→函数/数据→预处理/内存→字符串/算法
* D1-D7:二维数组、指针基础、字符串操作
* D8-D9:指针数组、多级指针、void/const
* D10-D13:函数传参、指针函数、递归/回调
* D14-D15:宏/类型定义、变量作用域
* D16:字符串算法(KMP等)
*/
/* 已覆盖:
* - 指针操作(一/二级指针、动态数组)
* - 内存管理(malloc/realloc)
* - 数据结构(链表、栈、快排)
* - 函数传参(指针传参、简单函数指针)
*/
/* 未覆盖但必需:
* 1. 指针:三维数组、void指针、const限定
* 2. 回调:函数指针数组、异步回调
* 3. 内存:Valgrind检测、内存池设计
* 4. 预处理:带副作用宏、条件编译
* 5. 数据结构:二叉树、哈希表
* 6. 算法:递归转迭代、双指针技巧
* 7. 标准库:qsort/bsearch、安全字符串函数
*/
/* 大厂高频考点:
* - 野指针、内存对齐
* - 缓冲区溢出防范
* - 段错误调试技巧
*/
// #self
// 所有知识点详细目录:
// 1二维数组的定义及初始化试听
// 二维数组的应用案例试听
// 二维数组应用-矩阵转置试听
// 二维数组应用-杨辉三角形试听
// 今日作业
// 2字符数组和字符串试听
// 字符数组和字符串-应用案例试听
// 二维字符数组试听
// 字符串输入输出函数
// 3指针的基本用法
// 指针的作用及学习方法05'24"
// 内存、地址、变量08'27"
// 指针和指针变量13'11"
// 指针的目标和“解引用”08'45"
// 指针的赋值14'25"
// 指针的大小11'36"
// 空指针10'05"
// 野指针及成因16'12"
// 野指针的危害是什么11'28"
// 如何避免野指针
// 4指针的运算
// 指针的算术运算17'48"
// 指针的算术运算-自增自减08'31"
// 指针算术运算符-自增自减应用109'07"
// 指针算术运算符-自增自减应用204'00"
// 指针的算术运算-应用08'32"
// 指针的算术运算-注意事项12'22"
// 指针的关系运算
// 5指针与数组
// 指针与数组基本用法11'57"
// 指针与数组使用注意事项09'49"
// 指针与数组相关笔试题
// 6指针与二维数组
// 一级指针与二维数组07'57"
// 数组指针与二维数组10'06"
// 数组指针应用12'33"
// 数组指针笔试题
// 7字符指针与字符串
// 字符指针与字符串基本用法09'15"
// 字符指针与字符串常量08'34"
// 字符指针与字符串应用
// 8指针数组
// 指针数组的基本用法14'06"
// 指针数组与二维数组11'41"
// 数组指针和指针数组的区别
// 9多级指针 void指针 const
// 多级指针基本用法10'36"
// 多级指针的运算13'45"
// 多级指针和指针数组06'09"
// void指针及用法11'38"
// const变量、const指针14'31"
// main函数的参数
// 10函数的基本用法及传参
// 函数的基本用法10'44"
// 函数的调用07'29"
// 函数的声明07'16"
// 函数的应用08'34"
// 函数传参-全局变量06'01"
// 函数的参数传递-值传递07'34"
// 函数的参数传递-值传递 -应用12'40"
// 函数的参数传递-指针传递
// 11函数的传参
// 函数传参-应用-字符串统计14'17"
// 一维数组在函数间传参14'26"
// 一维数组在函数间传参-总结04'00"
// 字符数组传参09'28"
// 二维数组在函数间传参-一级指针05'47"
// 二维数组在函数间传参 -行指针05'39"
// 二维数组在函数间传参 -
// 12指针函数
// 指针函数及用法11'44"
// 指针函数的返回值08'30"
// 指针函数-编写字符串拷贝函数13'17"
// 指针函数-编写字符串连接函数11'44"
// 指针函数案例
// 13递归函数和函数指针
// 递归函数及用法09'54"
// 递归函数应用04'37"
// 函数指针的基本用法16'07"
// 函数指针数组04'35"
// qsort函数的用法
// 14#define 和 typedef
// 预处理指令#define09'58"
// 没有值的宏定义15'34"
// 宏定义和 const 常量区别04'57"
// typedef的用法15'45"
// #define和typedef的比较06'27"
// 宏函数的使用
// 15变量的作用域和生命周期
// 变量存储类型-auto04'03"
// 变量存储类型-register07'03"
// 变量存储类型-static05'40"
// 变量存储类型-extern
// 16字符串处理函数
// 字符串函数上11'28"
// 字符串函数下08'48"
// strncpy函数09'12"
// strncat函数04'38"
// strncmp函数04'46"
// strchr函数04'09"
// strstr函数
return 0;
}
2.4 lv2后一半知识点:
#include
#include
#include
#include
#include
// ??????qsort???¨¦???¡è???????
// ====================== ??????¨¦?????¨¦???????? ======================
// 1. ¨¦?????¨¦?????????????????¡ì????/??????/????????¨¦?????
void wild_pointer_cause()
{
int a = 10;
int *new_ptr = &a;
// ?????????????????¨¦????????¨¦??
// *new_ptr = 10;
// int *uninit_ptr; // ??????¡ì????¨¦?????¨¦??
// *uninit_ptr = 10; // ???¨¦???????????????¨¦??
int *heap_ptr = (int *)malloc(sizeof(int));
free(heap_ptr); // ¨¦????????????????
// *heap_ptr = 20; // ???¨¦??????????????¨¦?????¨¦?????¨¦?????
int arr[5] = {1, 2, 3, 4, 5};
// int *over_ptr = arr + 5; // ??????¨¦????????
// int* yuejie_ptr = arr+10;
// *yuejie_ptr = 200;
// printf("¨¦????????¨¦?????%d\n",*yuejie_ptr);
}
// 2. ¨¦?????¨¦??????????????¡§???????????¡è???????¨¦????¡§¨¦???????????
// void wild_pointer_hazard() {
// int* ptr = NULL;
// *ptr = 10; // ??????¨¦???¡ì??????¡§??????????¨¦????
// }
// 3. ??????¨¦?????¨¦?????¨¦???????????????¡¦????
void avoid_wild_pointer()
{
int *safe_ptr = NULL; // ???????????¨¦?????NULL
safe_ptr = (int *)malloc(sizeof(int));
if (safe_ptr != NULL)
{
*safe_ptr = 42;
}
free(safe_ptr);
safe_ptr = NULL; // ¨¦????????????????????
}
// 4. ??????¨¦??????????¡§???????¡è???????
void null_pointer_safe()
{
int *p = NULL;
if (p == NULL)
{
p = (int *)malloc(sizeof(int));
// assert(p != NULL);
assert(p != NULL);
// #self VIP ???¡§?p!=nULL?????????????????????????????????¨¦???????
*p = 10;
free(p);
// #self ????????¨¦??
p = NULL;
}
}
// 5. ???¨¦??????¡è¡ì?¡ã?????????????¨¦??????????¡ã???
void pointer_size()
{
printf("64???????????????int* = %zu?????????char* = %zu??????\n???float?¡è¡ì?¡ã????%zu\n",
sizeof(int *), sizeof(char *), sizeof(double *)); // ?????????8 8
}
// ====================== ?????????¨¦???????? ======================
// 6. ???¨¦??????????????????????¡ã????????????¨¦???????????
void pointer_relation()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p1 = arr + 1;
int *p2 = arr + 3;
printf("p1 < p2: %s\n", (p1 < p2) ? "true" : "false"); // true
printf("p1 == arr+1: %s\n", (p1 == arr + 1) ? "true" : "false"); // true
}
// 7. ???¨¦???????????????? - ??¡§??????¨¦?????¨¦??????????????
void pointer_arithmetic_warning()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
// p -= 1; // ?????????¨¦?????
p += 4; // ????????????????????????????????
printf("?????????¨¦??: %d\n", *p); // 5
}
// 8. ???¨¦???????????????? - ?????¡§?????¡ã???¨¦????????
void pointer_arithmetic_application()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
for (int i = 0; i < 5; i++)
{
printf("arr[%d] = %d\n", i, *(p + i)); // ?????¡¦???arr[i]
}
}
// ====================== ?????????¨¦???????¡ã??? ======================
// 9. ???¨¦???????¡ã???????????????¨¦??????¡ã??????¨¦?????¨¦?¡¦¨¦?????
void array_pointer_question()
{
int arr[5] = {1, 2, 3, 4, 5};
printf("sizeof(arr) = %zu\n", sizeof(arr)); // 20?????¡ã????¡è¡ì?¡ã????
// #self ????????????20??? ??????????????
printf("sizeof(arr+0) = %zu\n", sizeof(arr + 0)); // 8??????¨¦???¡è¡ì?¡ã????
}
// 10. ???¨¦???????¡ã????????¡§??¡§??????¨¦??????????????????????????
void array_bound_check()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
for (int i = 0; i < 5; i++)
{
printf("%d ", p[i]); // ?????????¨¦??
}
// p[5] = 10; // ?????????¨¦?????
}
// 11. ??¡ã??????¨¦???????¡§???????????¡ã????????¨¦??¨¦????????
// #self ??????????????? vip
void array_ptr_application()
{
// int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// int (*row_ptr)[3] = arr; // ??????¨¦????????????????¡ã???
// for (int i = 0; i < 3; i++)
// {
// for (int j = 0; j < 3; j++)
// {
// printf("%d ", (*(row_ptr + i))[j]); // ?????¡¦???arr[i][j]
// }
// }
// #self !!!vip
int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int (*p)[3] = arr;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//!!!VIP ¡¦???????
printf("1 the numn :%d-%d:%d\n", i, j, *(p + i)[j]);
printf("2 the num: %d -%d : %d\n", i, j, p[i][j]);
}
}
printf("\n");
}
// #self #dachang ?????? ???????????????? ??????vip
void dachang_mianshi1(void)
{
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p1)[3] = arr;
int (*p2)[2][3] = &arr;
printf("%d\n", (*p1)[2]); // ?????3
printf("%d\n", (*p2)[1][2]); // ?????6
}
// ?????????
// p1???????*p1????????????
// p2?????????????????*p2???????????
void dachang_mianshi2(void)
{
int *p1[10]; //???????{-??10??int??????
int (*p2)[10]; // p2???10??int?????????
}
// 12. ??¡ã??????¨¦????????¨¦???????????¨¦???¡è¡ì???/????¡ì??????????
void array_ptr_question()
{
int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int (*row_ptr)[3] = arr;
printf("row_ptr?¡è¡ì?¡ã?: %zu\n", sizeof(row_ptr)); // 8??????¨¦???¡è¡ì?¡ã????
printf("????????????????: %d\n", row_ptr[1][2]); // 6
}
// ====================== ???????????????¨¦????????????? ======================
// 13. ????????¨¦???????????????????¡§????????¡§??????????????????
void char_ptr_application()
{
// copy string or char* by ptr ????????¡Á?¡¦???
char str1[20] = "Hello";
char *str2 = ", World!";
char *p1 = str1 + strlen(str1); // ??????str1?????
char *p2 = str2;
while (*p2 != '\0')
{
*p1++ = *p2++;
}
*p1 = '\0'; // ?????????????
printf("????????????: %s\n", str1); // Hello, World!
}
// 14. ????????¨¦?????????????????¨¦??????????????????¡è???????
// #self vip ?????????????¡ì??????????????
void char_ptr_constant()
{
char *const_str = "abc"; // ?????¡§??¡§?????????
// #self
const_str[0] = 'A';
printf("\n---->>>>????????????%s\n\n", *const_str);
// const_str[0] = 'A'; // ??????¨¦?????????????????????????
char stack_str[] = "abc"; // ?????¡§??¡§?????????????????
stack_str[0] = 'A';
}
// 15. ??¡ã??????¨¦????????¨¦????¡ã?????????????????????????????
// #self vip ??????¨¦??
void ptr_array_vs_array_ptr()
{
int arr[3][3];
int *ptr_arr[3]; // ???¨¦????¡ã????????????3???int*?????¡ã???
int (*arr_ptr)[3] = arr; // ??¡ã??????¨¦?????????????????3???int?????¡ã???
// #vip #self
}
// ====================== ???????????????¨¦?????main?????? ======================
// 16. ???¨¦????¡ã??????????????¡ã????????¡§???????????¡ã??????
void pointer_array_2d()
{
int *ptr_arr[2];
ptr_arr[0] = (int *)malloc(3 * sizeof(int)); // ??¡§??????¨¦????¡è?????????
ptr_arr[1] = (int *)malloc(3 * sizeof(int));
ptr_arr[0][0] = 1; // ?¡§????????????¡ã??????¨¦??
}
// 18. const???¨¦?????????¡ì????????¡è???????
void const_pointer()
{
int val = 10;
const int *cp1 = &val; // ?????????¨¦????????¨¦?????????????????
int *const cp2 = &val; // ???¨¦?????¨¦?????????????????¨¦??
int a = 100;
const int *ptra_1 = &a;
int *const ptra2_2 = &a;
int x = 2100;
const int *ptr1 = &x;
int *const ptr2 = &x;
// *cp1 = 20; // ¨¦????
// cp2 = &val; // ¨¦????
}
// 19. void???¨¦?????¨¦????¡§??????????????
void void_pointer_demo()
{
double d = 3.14;
void *vp = &d;
printf("void???double: %f\n", *(double *)vp); // ¨¦???????????????????????
}
// ====================== ??????????¡ã?????¡ã???¨¦?? ======================
// 20. ???¨¦?????¨¦???????¡è????????¡ã???
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// 21. ??????¨¦?? - ?????¡§?????????????????????
void value_pass_application()
{
printf("-->>\nin hte 21 value-pass-func:\n---->>\n");
int x = 5;
void value_pass(int *);
value_pass(&x); // ??????¨¦??
printf("x??????: %d\n", x); // ??????5
}
void value_pass(int *a)
{
*a = 10;
}
// 22. ?????¡ã?????? - ??¡§??????¨¦?????????????????¡§??????¨¦?????
int global_var = 100;
void global_pass()
{
printf("\n--->>> func22 global-pass!!!\n--->>>\n");
global_var = 200; // ?????????????¡§??????¨¦??
}
// ???????????¡ã??????
void test_swap()
{
int a = 5, b = 10;
swap(&a, &b);
printf("??¡è??????: a=%d, b=%d\n", a, b); // ??????10, 5
}
void test_global_pass()
{
global_pass();
printf("??¡§??????¨¦??: %d\n", global_var); // ??????200
}
// ====================== ??????????????¡ã????????? ======================
// 24. ??????¨¦???????????????????¡ã????????¡ã?????????3???
// #self !!!vip
// ¡Á?????????int (*p)[3] ??¡Á¨¦????
void pass_row_ptr(int (*arr)[3], int rows)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
// 25. ?????¡ì???¨¦???????????¨¦????¡§????????¡ã??????¨¦?????
void pass_first_ptr(int *arr, int rows, int cols)
{
for (int i = 0; i < rows * cols; i++)
{
printf("%d ", arr[i]);
}
}
// 26. ???????¡ã??????????????????????????¨¦????????
void char_arr_pass(char arr[], int len)
{
int count = 0;
for (int i = 0; i < len; i++)
{
if (arr[i] != '\0')
count++;
}
printf("???????¡ã???¨¦?????: %d\n", count);
}
// ====================== ????????¨¦???????? ======================
// 31. ???¨¦???????¡ã - ????????????????¡¦????????¡ã????
// #self ???¡¦????????????? vip
char *str_copy(const char *src)
{
char *dest = (char *)malloc(strlen(src) + 1);
assert(dest != NULL);
char *p = dest;
while (*src)
{
*p++ = *src++;
}
*p = '\0';
return dest;
}
void test_str_copy()
{
char *copy = str_copy("test");
printf("?¡è??????????: %s\n", copy);
free(copy);
}
// 32. ???¨¦???????¡ã???????????????¨¦?????????????????¨¦?????
// #self vip
// char* error_ptr_func() {
// char str[] = "test"; // ??????¨¦??????????¡ã?????????¨¦?????
// return str; // ???¨¦???????????¨¦?????¨¦??
// }
// ====================== ??????qsort????????¡ã?????? ======================
// 33. qsort?q????????????????????????¡ã??¡ã??????
int compare_asc(const void *a, const void *b)
{ // ???????????
return *(int *)a - *(int *)b;
}
int compFunc(const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
void qsort_demo()
{
int arr[] = {3, 1, 4, 2};
qsort(arr, 4, sizeof(int), compFunc);
for (int i = 0; i < 4; i++)
{
printf("\n--->>>qsort--->>>\n\n");
printf("%d ", arr[i]); // 1 2 3 4
}
printf("\n");
}
// 34. ?????¡ã???¨¦????¡ã?????????????¡§?????????
// #self !!!vip ????????
typedef int (*OpFunc)(int, int);
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
void func_ptr_array()
{
OpFunc ops[] = {add, subtract};
printf("5+3=%d\n", ops[0](5, 3)); // 8
printf("5-3=%d\n", ops[1](5, 3)); // 2
}
// #self !!!vp
typedef int (*FuncTypeTest)(int, int);
typedef int (*FuncType)(int, int);
int multi(int a, int b)
{
return a * b;
}
int devide(int a, int b)
{
return a / b;
}
void testFuncPtr(void)
{
FuncType funcList[] = {multi, devide};
printf("5*15 = %d \n", funcList[0](5, 15));
printf("5/15 = %d \n", funcList[1](5, 15));
}
// ====================== ??????¨¦??????????¡ã ======================
// 36. ¨¦??????????¡ã?????¡§?????????¨¦???????¡ã??????
int fibonacci(int n)
{
if (n <= 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
void test_fibonacci()
{
printf("fib(5) = %d\n", fibonacci(5)); // ??????5
}
// ====================== ???????????????typedef ======================
// 38. ????????¡ã????????¡§???????????¡ã??????
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define CONCAT(a, b) a##b
void macro_usage()
{
int max = MAX(5, 3); // 5
int var12 = CONCAT(var, 12); // ?????????var12
}
// 39. #define???typedef??????????????? vs ???????????????
typedef int IntArray[5]; // ????????¡ã?????????
// #self !!!vip
IntArray a, b;
int a1[5], b1[5];
// #define INT_ARRAY int[5] // ¨¦??????????????¡¦??¡ì?¨¦??
void type_compare()
{
IntArray arr1; // ?????????????????????
IntArray arr2; // ?????????????????????
}
// 40. typedef?????¡§???
typedef int IntArray[5]; // ????????¡ã?????????
void typedef_usage()
{
IntArray arr; // ?????¡¦??? int arr[5];
arr[0] = 10;
printf("typedef??¡ã???: %d\n", arr[0]);
}
// #self
// 41. ????????????const?????????????????????¡¦???????
const int CONST_NUM = 10; // ???????????????¡ã????
#define MACRO_NUM 10 // ????????????????????????
void const_vs_macro()
{
// CONST_NUM = 20; // ¨¦???????const???????????
// MACRO_NUM = 20; // ¨¦???????????????????????
}
/// @brief ?¨®?¡ì????
/// @param void
// #self : * only attach to the nearest element!!
// !!!!!vip
/// #self
void dachangmianshi3(void)
{
#define PTR_INT int *
typedef int *ptr_int;
PTR_INT a, b;
ptr_int x, y;
printf("--->>> %s %s \n", "int*", "int"); // ??????????????
printf("--->>> %s %s \n", "int*", "int*");
}
// ====================== ???????????????????¡è?????????? ======================
// 48. strncpy??????¨¦?????¨¦???????¡¦??????
char *my_strncpy(char *dest, const char *src, size_t n)
{
assert(dest != NULL && src != NULL);
size_t i = 0;
char *tempPtr = dest;
while (i < n && n > 0 && src[i])
{
dest[i] = src[i];
i++;
}
while (i < n)
{
dest[i] = '\0';
// n--;
i++;
}
return tempPtr;
}
void test_strncpy()
{
char dest[10] = {0};
my_strncpy(dest, "hello", 3);
printf("strncpy---?¡¦?¡¦?¡¦?¡¦: %s\n", dest); // ??????"hel"
}
// 47. strncat??????¨¦?????¨¦??????????????
char *my_strncat(char *dest, const char *src, size_t n)
{
// assert(dest != NULL && src != NULL);
// size_t dest_len = strlen(dest);
// for (size_t i = 0; i < n && src[i]; i++)
// {
// dest[dest_len + i] = src[i];
// }
// dest[dest_len + n] = '\0'; // ?????????????
// return dest;
assert(dest != NULL && src != NULL);
size_t len = strlen(dest);
char *res = dest;
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++)
{
dest[len + i] = src[i];
}
dest[i + len] = '\0';
return res;
}
void test_str_cat(void)
{
printf("\n---->>>>>\n strcat??????\n");
// ?????????????¨®??????????????#self !!!vip??????????
char dest[10] = {'1', '2', '\0'};
char src[] = {'3', '4', 'a', '\0'};
char *res = my_strncat(dest, src, 3);
printf("--->>> \n str cat func --->>> \n%s", res);
}
// 46. strncmp??????¨¦??????????????
int my_strncmp(const char *s1, const char *s2, size_t n)
{
// assert(s1 != NULL && s2 != NULL);
// for (size_t i = 0; i < n && s1[i] && s2[i]; i++)
// {
// if (s1[i] != s2[i])
// return s1[i] - s2[i];
// }
// return 0;
assert(s1 != NULL && s2 != NULL);
for (size_t i = 0; i < n; i++)
{
char c1 = s1[i] ? s1[i] : '\0';
char c2 = s2[i] ? s2[i] : '\0';
if (c1 != c2)
{
return c1 - c2;
}
}
return 0;
}
void test_strncmp(void)
{
char s1[] = {'1', '2', '3', '5'};
char s2[] = {'1', '2', '3'};
printf("\n--->>>\nstrnCmp??????????\n%d", my_strncmp(s1, s2, 4));
}
// 45. strchr???????????????¨¦?????????¡ã???
char *my_strchr(const char *str, int c)
{
printf("\n___>>>>> in the strchar func!!\n");
assert(str != NULL);
const char *p = str;
while ((*p) != '\0')
{
if (*p == (char)c)
{
return (char *)p;
}
p++;
}
return (char)c == '\0' ? (char *)p : NULL;
}
void test_strchar(void)
{
// #self code robotness ´úÂ뽡׳ÐÔ!!!vip
char test[] = {'1', '2', 'a', 'b', 'c', 'f', 'l', '6', '\0'};
char *res = my_strchr(test, '7');
if (!res)
{
printf("not found!!\n");
}
else
{
printf("founded !!!! res is %c \n\n", *res);
}
}
// 44. strstr???????????????¨¦?????????¡ã???
char *my_strstr(const char *haystack, const char *needle)
{
// #self must do it yourself
assert(haystack != NULL && needle != NULL);
if (*needle == '\0')
{
return NULL;
}
while (haystack != NULL && needle != NULL)
{
const char *h = haystack;
const char *n = needle;
while (h && n && h == n)
{
h++;
n++;
}
if (*n == '\0')
{
return (char*)haystack;
}
haystack++;
}
if (*haystack == '\0')
{
return NULL;
}
}
void test_strstr(void)
{
char haystack[] = {'1', 'a', '2', 'b', 'c', '\0'};
char needle[] = {'b', 'c', '\0'};
char* res = strstr(haystack, needle);
printf("-->>>>>>\n now in strstr func, res is :%c \n", (*res));
}
int main(int argc, char *argv[])
{
printf("=== C???¡§????¨¦??????????????????????????????? ===\n\n");
// ??????¨¦?????¨¦????????
printf("??????¨¦?????¨¦??????????????:\n");
wild_pointer_cause();
pointer_size();
null_pointer_safe();
printf("\n");
// ?????????¨¦????????
printf("?????????¨¦??????????????:\n");
pointer_relation();
pointer_arithmetic_application();
printf("\n");
// function 1-8
// ?????????¨¦???????¡ã???
// function 9->
printf("?????????¨¦???????¡ã?????????:\n");
// func 9
array_pointer_question();
printf(">>>>>>>> test shuzuPtr!!!\n");
// func 11
array_ptr_application();
printf("\n");
// ???????????????¨¦?????????????
printf("???????????????¨¦???????????????????:\n");
// func 13
char_ptr_application();
// char_ptr_constant();
printf("\n");
// ???????????????¨¦????????
printf("???????????????¨¦????????:\n");
// func 18
const_pointer();
void_pointer_demo();
printf("\n");
// ??????????¡ã?????¡ã???¨¦??
printf("??????????¡ã?????¡ã???¨¦????????:\n");
// func 21
value_pass_application();
// func 22
test_global_pass();
test_swap();
printf("\n");
// ??????????????¡ã?????????
printf("??????????????¡ã???????????????:\n");
// func 24
printf("--->>>in the main: calling func24--->>>\n");
int arr2d[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
pass_row_ptr(arr2d, 3);
printf("\n");
// ????????¨¦???????¡ã??????
printf("????????¨¦???????¡ã??????:\n");
test_str_copy();
printf("\n");
// ??????qsort????????¡ã???¨¦????????
printf("??????qsort????????¡ã???¨¦????????:\n");
// func 33
qsort_demo();
func_ptr_array();
// func 34
testFuncPtr();
printf("\n");
// ??????¨¦??????????¡ã??????
// func 36
printf("??????¨¦??????????¡ã??????:\n");
test_fibonacci();
printf("\n");
// ?????????typedef??????
printf("?????????typedef??????:\n");
typedef_usage();
printf("\n");
printf("--->>> \n ?¨®?¡ì???? \n");
dachangmianshi3();
// ???????????????????¡è?????????¡ã??????
printf("???????????????????¡è?????????¡ã??????:\n");
// #self ¡Á??????? str????
test_strncpy();
printf("\n");
test_str_cat();
test_strncmp();
test_strchar();
test_strstr();
printf("=== ?????????????????? ===\n");
return 0;
}
lv2 总结:
#include
#include
#include
#include
// 结构体定义
// 定义 Node 结构体,用于多级指针操作和链表
struct Node
{
int value; // 节点值
struct Node *next; // 指向下一个节点的指针(用于链表)
struct Node **children; // 子节点数组(用于多级指针)
int child_count; // 子节点数量
};
// 定义 Person 结构体,包含姓名和年龄
struct Person
{
char name[10];
int age;
};
// 定义栈结构体
struct stack
{
int data[100]; // 假设栈最大容量为 100
int top;
};
#define maxL 99 // 栈的最大容量
// 函数声明
// 栈操作函数
void initStack(struct stack *s);
int isEmpty(struct stack *s);
int isFull(struct stack *s);
void pushStack(struct stack *s, int value);
int popStack(struct stack *s);
int peekTop(struct stack *s);
// 链表操作函数
struct Node *insert_atFirst(struct Node *head, int data);
void print_List(struct Node *node);
// 排序函数
void quick_Sort(int arr[], int low, int high);
int partition(int arr[], int low, int high);
void swap(int *a, int *b);
// 字符串处理函数
char *my_strstr(const char *haystack, const char *needle);
char *my_strncpy(char *dest, const char *src, size_t n);
char *my_strncat(char *dest, const char *src, size_t n);
int my_strncmp(const char *s1, const char *s2, size_t n);
char *my_strchr(const char *str, int c);
char *str_copy(const char *src);
// 其他函数
void wild_pointer_cause();
void pointer_relation();
void pointer_arithmetic_application();
void array_pointer_question();
void array_ptr_application();
void char_ptr_application();
void const_pointer();
void value_pass_application();
void pass_row_ptr(int arr[][3], int rows);
void qsort_demo();
void func_ptr_array();
void testFuncPtr();
int fibonacci(int n);
void test_fibonacci();
void typedef_usage();
void dachangmianshi3();
void test_strncpy();
void test_str_cat();
void test_strncmp();
void test_strchar();
void test_strstr();
void arrSort(char *arr[], int n);
int *dy_alloc(int n);
void add_child(struct Node *parent, struct Node *child);
void *arrtoPtrInt(void *x);
int getStrLen(char *a);
char *strCpyFn(char *dest, char *src);
void zhuanzhi(int arr[3][3]);
void connect_char(char *a, char *b);
// 加法函数
int add(int a, int b);
// 减法函数
int subtract(int a, int b);
// 测试字符串复制函数
void test_str_copy();
// 栈操作函数实现
// 初始化栈
void initStack(struct stack *s)
{
s->top = -1;
}
// 判断栈是否为空
int isEmpty(struct stack *s)
{
return s->top == -1 ? 1 : -100;
}
// 判断栈是否已满
int isFull(struct stack *s)
{
return s->top == maxL ? 1 : 0;
}
// 入栈操作
void pushStack(struct stack *s, int value)
{
if (!isFull(s))
{
s->data[++(s->top)] = value;
}
}
// 出栈操作
int popStack(struct stack *s)
{
if (!isEmpty(s))
{
return s->data[(s->top)--];
}
return -1;
}
// 获取栈顶元素
int peekTop(struct stack *s)
{
return s->data[s->top];
}
// 链表操作函数实现
// 在链表头部插入节点
struct Node *insert_atFirst(struct Node *head, int data)
{
struct Node *n_node = (struct Node *)malloc(sizeof(struct Node));
n_node->value = data; // 修改为正确的成员名 value
n_node->next = head; // 使用正确的成员名 next
n_node->children = NULL; // 初始化子节点数组
n_node->child_count = 0; // 初始化子节点数量
return n_node;
}
// 打印链表节点数据
void print_List(struct Node *node)
{
struct Node *l = node;
while (l != NULL)
{
printf("当前打印的节点:数据为 %d \n", l->value); // 修改为正确的成员名 value
l = l->next; // 使用正确的成员名 next
}
}
// 排序函数实现
// 快速排序
void quick_Sort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quick_Sort(arr, low, pi - 1);
quick_Sort(arr, pi + 1, high);
}
}
// 分区函数
int partition(int arr[], int low, int high)
{
int pi = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; j++)
{
if (arr[j] <= pi)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return i + 1;
}
// 交换两个整数的值
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// 字符串处理函数实现
// 自定义 strstr 函数,查找子字符串
char *my_strstr(const char *haystack, const char *needle)
{
assert(haystack != NULL && needle != NULL);
if (*needle == '\0')
{
return NULL;
}
while (*haystack)
{
const char *h = haystack;
const char *n = needle;
while (*h && *n && *h == *n)
{
h++;
n++;
}
if (*n == '\0')
{
return (char *)haystack;
}
haystack++;
}
return NULL;
}
// 自定义 strncpy 函数,复制指定长度的字符串
char *my_strncpy(char *dest, const char *src, size_t n)
{
assert(dest != NULL && src != NULL);
size_t i = 0;
char *tempPtr = dest;
while (i < n && src[i])
{
dest[i] = src[i];
i++;
}
while (i < n)
{
dest[i] = '\0';
i++;
}
return tempPtr;
}
// 自定义 strncat 函数,连接指定长度的字符串
char *my_strncat(char *dest, const char *src, size_t n)
{
assert(dest != NULL && src != NULL);
size_t len = strlen(dest);
char *res = dest;
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++)
{
dest[len + i] = src[i];
}
dest[i + len] = '\0';
return res;
}
// 自定义 strncmp 函数,比较指定长度的字符串
int my_strncmp(const char *s1, const char *s2, size_t n)
{
assert(s1 != NULL && s2 != NULL);
for (size_t i = 0; i < n; i++)
{
char c1 = s1[i] ? s1[i] : '\0';
char c2 = s2[i] ? s2[i] : '\0';
if (c1 != c2)
{
return c1 - c2;
}
}
return 0;
}
// 自定义 strchr 函数,查找字符
char *my_strchr(const char *str, int c)
{
printf("\n___>>>>> in the strchar func!!\n");
assert(str != NULL);
const char *p = str;
while (*p)
{
if (*p == (char)c)
{
return (char *)p;
}
p++;
}
return (char)c == '\0' ? (char *)p : NULL;
}
// 自定义字符串复制函数
char *str_copy(const char *src)
{
char *dest = (char *)malloc(strlen(src) + 1);
assert(dest != NULL);
char *p = dest;
while (*src)
{
*p++ = *src++;
}
*p = '\0';
return dest;
}
// 其他函数实现
// 演示野指针的成因
void wild_pointer_cause()
{
int a = 10;
int *new_ptr = &a;
int *heap_ptr = (int *)malloc(sizeof(int));
free(heap_ptr);
int arr[5] = {1, 2, 3, 4, 5};
}
// 演示指针的关系运算
void pointer_relation()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p1 = arr + 1;
int *p2 = arr + 3;
printf("p1 < p2: %s\n", (p1 < p2) ? "true" : "false");
printf("p1 == arr+1: %s\n", (p1 == arr + 1) ? "true" : "false");
}
// 演示指针的算术运算
void pointer_arithmetic_application()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
for (int i = 0; i < 5; i++)
{
printf("arr[%d] = %d\n", i, *(p + i));
}
}
// 演示数组指针相关问题
void array_pointer_question()
{
int arr[5] = {1, 2, 3, 4, 5};
printf("sizeof(arr) = %zu\n", sizeof(arr));
printf("sizeof(arr+0) = %zu\n", sizeof(arr + 0));
}
// 演示数组指针的应用
void array_ptr_application()
{
int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int (*p)[3] = arr;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("1 the numn :%d-%d:%d\n", i, j, *(p + i)[j]);
printf("2 the num: %d -%d : %d\n", i, j, p[i][j]);
}
}
printf("\n");
}
// 演示字符指针的应用
void char_ptr_application()
{
char str1[20] = "Hello";
char *str2 = ", World!";
char *p1 = str1 + strlen(str1);
char *p2 = str2;
while (*p2)
{
*p1++ = *p2++;
}
*p1 = '\0';
printf("拼接后的字符串: %s\n", str1);
}
// 演示 const 指针的使用
void const_pointer()
{
int val = 10;
const int *cp1 = &val;
int *const cp2 = &val;
}
// 演示值传递的应用
void value_pass_application()
{
printf("-->>\nin hte 21 value-pass-func:\n---->>\n");
int x = 5;
void value_pass(int *);
value_pass(&x);
printf("x的值不变: %d\n", x);
}
// 传递二维数组的行指针
void pass_row_ptr(int arr[][3], int rows)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
// 比较函数,用于 qsort
int compare_asc(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
// 演示 qsort 函数的使用
void qsort_demo()
{
int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
int n = sizeof(arr) / sizeof(arr[0]);
qsort(arr, n, sizeof(int), compare_asc);
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 演示函数指针数组的使用
int add(int a, int b);
int subtract(int a, int b); // 修正函数声明
void func_ptr_array()
{
typedef int (*OpFunc)(int, int);
OpFunc ops[] = {add, subtract};
printf("5+3=%d\n", ops[0](5, 3));
printf("5-3=%d\n", ops[1](5, 3));
}
// 测试函数指针
void testFuncPtr()
{
// 示例代码可根据实际需求添加
}
// 斐波那契数列递归实现
int fibonacci(int n)
{
if (n <= 1)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// 测试斐波那契数列
void test_fibonacci()
{
printf("fib(5) = %d\n", fibonacci(5));
}
// 演示 typedef 的使用
void typedef_usage()
{
typedef int IntArray[5];
IntArray arr;
arr[0] = 10;
printf("typedef 使用示例: %d\n", arr[0]);
}
// 大厂面试相关代码
void dachangmianshi3()
{
#define PTR_INT int *
typedef int *ptr_int;
PTR_INT a, b;
ptr_int x, y;
printf("--->>> %s %s \n", "int*", "int");
printf("--->>> %s %s \n", "int*", "int*");
}
// 测试 strncpy 函数
void test_strncpy()
{
char dest[10] = {0};
my_strncpy(dest, "hello", 3);
printf("strncpy---复制结果: %s\n", dest);
}
// 测试 strncat 函数
void test_str_cat()
{
printf("\n---->>>>>\n strcat 函数测试\n");
char dest[10] = {'1', '2', '\0'};
char src[] = {'3', '4', 'a', '\0'};
char *res = my_strncat(dest, src, 3);
printf("--->>> \n str cat func --->>> \n%s", res);
}
// 测试 strncmp 函数
void test_strncmp()
{
char s1[] = {'1', '2', '3', '5'};
char s2[] = {'1', '2', '3'};
printf("\n--->>>\nstrnCmp 函数测试结果:\n%d", my_strncmp(s1, s2, 4));
}
// 测试 strchr 函数
void test_strchar()
{
char test[] = {'1', '2', 'a', 'b', 'c', 'f', 'l', '6', '\0'};
char *res = my_strchr(test, '7');
if (!res)
{
printf("not found!!\n");
}
else
{
printf("founded !!!! res is %c \n\n", *res);
}
}
// 测试 strstr 函数
void test_strstr()
{
char haystack[] = {'1', 'a', '2', 'b', 'c', '\0'};
char needle[] = {'b', 'c', '\0'};
char *res = my_strstr(haystack, needle); // 使用自定义的 my_strstr 函数
if (res)
{
printf("-->>>>>>\n now in strstr func, res is :%c \n", *res);
}
else
{
printf("-->>>>>>\n now in strstr func, not found \n");
}
}
// 对字符串数组进行排序
void arrSort(char *arr[], int n)
{
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - 1 - i; j++)
if (strcmp(arr[j], arr[j + 1]) > 0)
{
char *temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// 动态分配数组
int *dy_alloc(int n)
{
int *res = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
res[i] = i;
return res;
}
// 添加子节点
void add_child(struct Node *parent, struct Node *child)
{
parent->children = realloc(parent->children, (parent->child_count + 1) * sizeof(struct Node *));
parent->children[parent->child_count++] = child;
}
// void 指针通用类型转换
void *arrtoPtrInt(void *x)
{
return (char *)(x) + 2;
}
// 获取字符串长度
int getStrLen(char *a)
{
char *p = a;
while (*p)
p++;
return p - a;
}
// 字符串拷贝函数
char *strCpyFn(char *dest, char *src)
{
char *result = dest;
while (*src)
*dest++ = *src++;
*dest = '\0';
return result;
}
// 矩阵转置
void zhuanzhi(int arr[3][3])
{
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
}
// 连接两个字符串
void connect_char(char *a, char *b)
{
char *p1 = a + strlen(a);
while (*b)
{
*p1 = *b;
p1++;
b++;
}
*p1 = '\0';
}
// 加法函数
int add(int a, int b)
{
return a + b;
}
// 减法函数
int subtract(int a, int b)
{
return a - b;
}
// 测试字符串复制函数
void test_str_copy()
{
char *copy = str_copy("test");
printf("复制后的字符串: %s\n", copy);
free(copy);
}
void value_pass(int *p)
{
printf("在 value_pass 函数中:原值 = %d\n", *p);
*p = *p + 10;
printf("在 value_pass 函数中:新值 = %d\n", *p);
}
// 主函数
int main()
{
printf("=== C 语言知识点综合测试 ===\n\n");
// 野指针相关测试
printf("野指针相关测试:\n");
wild_pointer_cause();
printf("\n");
// 指针关系和算术运算测试
printf("指针关系和算术运算测试:\n");
pointer_relation();
pointer_arithmetic_application();
printf("\n");
// 数组指针测试
printf("数组指针测试:\n");
array_pointer_question();
array_ptr_application();
printf("\n");
// 字符指针测试
printf("字符指针测试:\n");
char_ptr_application();
printf("\n");
// const 指针测试
printf("const 指针测试:\n");
const_pointer();
printf("\n");
// 值传递测试
printf("值传递测试:\n");
value_pass_application();
printf("\n");
// 二维数组行指针传递测试
printf("二维数组行指针传递测试:\n");
int arr2d[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
pass_row_ptr(arr2d, 3);
printf("\n");
// 字符串复制测试
printf("字符串复制测试:\n");
test_str_copy(); // 确保函数已声明和定义
printf("\n");
// qsort 函数测试
printf("qsort 函数测试:\n");
qsort_demo();
func_ptr_array();
testFuncPtr();
printf("\n");
// 斐波那契数列测试
printf("斐波那契数列测试:\n");
test_fibonacci();
printf("\n");
// typedef 使用测试
printf("typedef 使用测试:\n");
typedef_usage();
printf("\n");
// 大厂面试相关代码测试
printf("大厂面试相关代码测试:\n");
dachangmianshi3();
printf("\n");
// 字符串处理函数测试
printf("字符串处理函数测试:\n");
test_strncpy();
test_str_cat();
test_strncmp();
test_strchar();
test_strstr();
printf("\n");
// 栈操作测试
printf("栈操作测试:\n");
struct stack s;
initStack(&s);
printf("初始化后,栈是否为空: %d\n", isEmpty(&s));
pushStack(&s, 1);
printf("压入 1 后,栈是否为空: %d\n", isEmpty(&s));
pushStack(&s, 2);
pushStack(&s, 3);
printf("栈顶元素: %d\n", peekTop(&s));
pushStack(&s, 4);
printf("栈顶元素: %d\n", peekTop(&s));
popStack(&s);
printf("弹出元素后,栈顶元素: %d\n", peekTop(&s));
printf("\n");
// 链表操作测试
printf("链表操作测试:\n");
struct Node *head_node = NULL;
head_node = insert_atFirst(head_node, 123);
printf("第一个节点: %d\n", head_node->value); // 修改为正确的成员名 value
head_node = insert_atFirst(head_node, 4);
printf("第二个节点: %d\n", head_node->value); // 修改为正确的成员名 value
print_List(head_node);
printf("\n");
// 快速排序测试
printf("快速排序测试:\n");
int arr11[] = {4, 5, 6, 7, 15, 234, 46, 698, 238, 258, 45, 2, 36, 26, 123, 77, 5, 48, 45, 2, 5, 325, 32, 1, 6};
int len = sizeof(arr11) / sizeof(arr11[0]);
quick_Sort(arr11, 0, len - 1);
for (int i = 0; i < len; i++)
{
printf("排序后输出的结果: %d\n", arr11[i]);
}
printf("\n");
printf("=== 测试结束 ===\n");
return 0;
}
2 .6 c语言源代码:文件下载:
附在本文的资源绑定了直接下载我上传的C语言文件文件就可以!
觉得我写得不错的话麻烦点赞关注收藏感谢了大家对我技术干货硬核内容的喜欢就是支持我写技术帖的最大动力!