当前位置: 首页 > news >正文

我的创作纪念日——《惊变256天》

在这里插入图片描述

我的创作纪念日——《惊变256天》

    • 机缘
    • 收获
    • 日常
    • 成就
    • 憧憬

最近,博主收到了 CSDN 发来的系统消息,这才惊觉,自上次第128天创作纪念日之后,竟又悄然走过了 128 天。站在 256 天这个颇具意义的里程碑前回望,博主在2023 年 8 月 29 日那天创作第一篇博客的情景依然历历在目。

彼时,博主怀着忐忑又兴奋的心情,敲下了第一篇博客:讲解LeetCode第1题:两数之和(完整代码)。未曾想,这看似寻常的举动,竟成了漫漫创作之旅的起点。

起初,博主每一次点击 “发布” 键,都像把精心打磨的作品置于众目睽睽之下,既期待共鸣,又害怕被否定。但是连续几次的发布并没有什么回应,慢慢的博主的创作越来越少,但是在几近放弃时候博主选择了坚持下来,而如今回望却发现自己已经走了很远。

机缘

博主是于 2023 年 9 月 1 日踏入大学校门,从入学伊始呢博主便确定了本科毕业后直接就业的选择。因此,平日空闲的时候,博主便常通过手机了解一些计算机专业学生的就业情况,也正是在这样的探索中,博主慢慢知晓了 CSDN 这个 APP,然后就在 2023 年 10 月 11 日注册了账号。不过,起初博主只是偶尔打开浏览,并未深入使用。

后来,博主从一些过来人分享的经验中得知,经常撰写博客在面试时能成为加分项,从那时起,以就业为目标的博主心里便萌生了写博客的念头。但由于完全不懂如何写博客,起初并未真正付诸行动。

时光流转,转眼间时间就到了大一结束的那个暑假。某一天,博主突然想起写博客这件事,于是便在 B 站上学习如何写博客。这才了解到,需要先掌握一种名为 Markdown 的轻量型标记语言。当学完这门语言后,博主又面临新的困惑:该创作什么类型的文章呢?

这时,眼前记录着 LeetCode 题解和知识要点的笔记本引发了博主的思考:“本子上记了这么多知识点,自己又翻开看过几次呢?”,于是,博主翻开笔记本的第一页,看到 “两数之和” 的题目,灵感涌现,就此诞生了第一篇博客:讲解LeetCode第1题:两数之和(完整代码)。此后,博主又陆续撰写了几篇 LeetCode 习题讲解,当然也都反响平平,不过博主还在不定期的更新。

那时,博主还只是独自在 CSDN 上发布零散的 LeetCode 或洛谷题解,关注者寥寥,更新也毫无规律,全凭兴致所至。

因此,博主还没发几篇博客,上半学期就结束了。在寒假里的某一天,博主忽然发现自己对之前学过的一些内容已经记忆模糊了,却又因没有学习记录而只能重新翻书。基于此,博主萌生了将从 C 语言开始的所有学习内容都写成博客的想法,目的是方便自己随时回顾,同时通过不断总结来牢固已经掌握的知识点。秉持着这一信念,即便平时再忙,博主睡前也要坚持写一点博客,因此现在博主的博客大都是这样一天一点、积少成多积累而来的。

然而,C 语言的内容还差两章未更新完,寒假便结束了,新学期如期而至。在新学期里,博主通过 CSDN 平台结识了一群同样通过博客记录学习过程的小伙伴。大家彼此支持,此前博主博客评论区总是一片冷清,如今却多了许多互动。每天看到自己的博客能得到小伙伴们的支持,博主心中便充满了继续更新的动力。同时,看到同龄小伙伴每周都能创作出多篇优质博文,博主也深受激励,不再像从前那样随意更新,而是给自己定下规矩:每周必须完成两篇高质量的博客。


收获

截止到目前,博主在 CSDN 平台已收获 720 多名粉丝,累计获得 1700 多个点赞、1400 多次收藏以及 500 多条评论。这些数据于博主而言,绝非冰冷的数字,而是无数个日夜坚持创作的鲜活记录。每当看到粉丝数量从三位数突破至新的台阶,每当注视着点赞、收藏的数字一点点的变大,博主总能清晰感受到时间的流淌。

博主通过之前持续的博客创作,在知识梳理与文字表达上积累了许多经验,现在博主对内容质量的把控也愈发严格。从最初对 Markdown 语法的生疏运用,到如今能流畅地将复杂知识点拆解为逻辑清晰的技术博文,每一次创作都是对自我的打磨与提升。

在创作的过程中,博主的努力也多次获得认可 —— 除了获得许多小伙伴的支持,也得到了CSND平台的认可:(例如一下几个:)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

博主深知,没有大家的认可,便没有这些榜单上的成绩,也没有持续创作的热情。因此,在今后的日子里,博主定会继续力求每篇博客都做到逻辑清晰、干货满满,让大家能博客中收获更多。

同时,也会更加注重与大家的互动,倾听大家的需求与建议,让博客真正成为一个共同学习、共同进步的平台。

日常

日常里,博主主要专注于专业课的学习(当然,博主的学习范围并不局限于学校课程所涵盖的内容)。一般每学完一到两个章节,便会停下脚步,悉心梳理所学知识点,将其整理成博客与大家分享。

当然创作博客这件事情确实还是挺费时间和精力的,但是经过这段时间的坚持,博主愈发觉得用创作博客来巩固之前的学习内容的这种学习方法行之有效 —— 譬如:对学过的知识印象比以往更加清晰深刻,知识体系也在整理过程中逐渐脉络分明。因此,博主下定决心,会将写博客这一习惯长期坚持下去,创作博客也早已成为博主日常学习中不可或缺的一部分。

倘若你同样是一名大学生,且打算未来从事 C++ 相关岗位,不妨关注博主。你可以通过博主的博客查漏补缺,梳理知识盲区,同时也能提前了解后续的学习方向,明晰技术进阶路径。

在此,博主郑重许诺:只要今后博主仍在 IT 行业深耕,持续学习计算机相关知识,就一定会将所学内容整理成文,以博客的形式分享给大家,与大家共同成长。

所以,欢迎大家关注博主,让博主成为你漫长学习道路上的同行者与见证者。博主期待以博客为桥梁,结识更多志同道合的朋友,一起在代码的世界里披荆斩棘,携手进步!


成就

在这段持续创作的时光里,博主撰写了许多代码示例,而《数据结构初阶》系列博客中关于栈、队列、链表等基础数据结构的实现代码,对于博主而言颇具特殊意义。

回想起初次接触数据结构的经历,那时的博主仅仅停留在书本上的名词概念 —— 知道 “链表” 是一种链式存储结构,“队列” 遵循先进先出原则,却从未真正动手实现过任何一个数据结构。

那些看似清晰的理论,在脱离文字描述后,往往暴露出许多模糊的细节:链表的头指针该如何初始化?循环队列的队满条件为何要设计为(rear + 1) % capacity == front?这些问题一直萦绕在博主的脑海里,最后博主也醒悟了过来:我的目标是要找到的一个不错的软件开发工作,不应该只是跟着学校的教学要求走,作为一名合格的开发程序员,这些数据结构的实现应该都是信手捏来的事情。

而这次通过博客分享数据结构的实现代码,对博主来说既是一场充满挑战的 “通关之旅”,也是见证成长的 “成就解锁” 过程。

以链表为例,从最初频繁出现的指针越界错误,到逐步理清malloc分配内存与指针指向的逻辑。记得在实现循环队列时,为了避免 “假溢出” 问题,反复推敲队头与队尾指针的移动逻辑,甚至在草稿纸上画出环形数组的状态变化图,最终才提炼出通过取模运算实现循环存储的核心逻辑。这种从 “纸上谈兵” 到 “落地成码” 的转变,不仅让抽象概念变得触手可及,更让博主深刻体会到:数据结构的灵魂不在于定义,而在于如何用代码让其‘活起来’

这些代码或许不够完美,却真实记录了博主从 “理论学习者” 到 “实践创作者” 的蜕变。每一个mallocfree的配对,每一次条件判断的调整,博主都能清晰地感觉到自己正在变得越来越熟练。

之前有看过博主写的博客的小伙伴的都知道,博主的代码片段中的经常会添加一些“注意:XXXXXXXXX。“,这样的内容—— 这些看似琐碎的提醒,实则是博主踩过无数 “坑” 后的经验沉淀。对博主而言,它们不仅是技术的输出,更是对曾经懵懂的自己的一次致敬:那些曾经觉得晦涩难懂的知识,如今竟能以代码的形式清晰呈现,并成为帮助他人理解数据结构的桥梁。

博主撰写的代码示例中若要展示一段代码的话,博主愿以循环队列的 C 语言实现为例:

-----------------------------CircularQueue.c-----------------------------#include "CircularQueue.h"/*-----------------------------------------辅助工具函数-----------------------------------------*/
/*** @brief 检查并扩容循环队列的存储空间** @param pcque 指向循环队列的指针** @note 该函数完成以下工作:*       1. 检查队列是否已满*       2. 计算新容量(初始为0时设为4,否则2倍扩容)*       3. 使用realloc扩容存储数组*       4. 更新队列的容量字段** @warning 扩容后不处理元素位置的调整(循环队列可能需要特殊处理)*/
//1.实现:“循环队列的扩容”辅助函数
void CQCheckCapacity(CQ* pcque)
{if (pcque->capacity == 0)  //特殊处理初始情况{int newCapacity = 4;CQDataType* tmp = (CQDataType*)malloc(newCapacity * sizeof(CQDataType));if (!tmp) {perror("malloc fail");exit(EXIT_FAILURE);}pcque->a = tmp;pcque->capacity = newCapacity;}else if (pcque->size == pcque->capacity-1) //容量为capacity的循环队列最多只能存储capacity-1个元素{//1.1:判断需要扩容的容量的大小int newCapacity = pcque->capacity * 2;//1.2:使用realloc进行扩容CQDataType* tmp = (CQDataType*)realloc(pcque->a, newCapacity*sizeof(CQDataType));if (tmp == NULL){perror("realloc fail");return;}//更新数组的指针 + 循环队列的容量pcque->a = tmp;pcque->capacity = newCapacity;}
}//2.实现:“打印循环队列”的辅助函数
void CQPrint(CQ* pcque)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用//情况1:循环队列为空队列if (CQEmpty(pcque)) return;//情况2:循环队列非空队列//2.1:定义一个变量记录打印循环队列中的元素的数量int count = 0;//2.2:循环打印队列中的元素int pcur = pcque->front;   //注意:这里一定要使用一个临时的指针进行遍历循环队列,防止pcque指针的移动导致队列结构错乱while (count < pcque->size) {printf("%d ", pcque->a[pcur]);pcur = (pcur + 1) % pcque->capacity;count++;}printf("\n");
}/*-----------------------------------------核心功能函数-----------------------------------------*/
/*** @brief 初始化循环队列** @param pcque 指向需要初始化的循环队列结构体的指针** @note 该函数完成以下工作:*       1. 检查指针有效性(断言保护)*       2. 初始化队列的基本状态:*          - 当前元素数量(size)置为0*			- 当前队列容量(capacity)置为0*          - 队头指针(front)置为0*          - 队尾指针(rear)置为0*          - 数据存储数组指针(a)置为NULL** @warning* - 使用前必须确保pcque指针有效* - 该初始化不会分配存储空间,首次插入元素时会自动扩容*/
//1.实现:“循环队列的初始化”操作
void CQInit(CQ* pcque)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用pcque->size = 0;pcque->capacity = 0;pcque->front = 0;pcque->rear = 0;pcque->a = NULL;
}//2.实现:“循环队列的销毁”操作
void CQDestroy(CQ** ppcque)
{assert(ppcque);  //断言检查1:确保传入的指针是非空指针,防止对空指针进行解引用assert(*ppcque); //断言检查2:确保队列指针有效,防止对空指针进行解引用(建议加上)/*----------第一步:释放动态数组内存----------*/free((*ppcque)->a);(*ppcque)->a = NULL;/*----------第一步:重置队列状态----------*/(*ppcque)->size = (*ppcque)->capacity = 0;(*ppcque)->front = (*ppcque)->rear = 0;/*----------第一步:释放队列结构体内存----------*/free(*ppcque);*ppcque = NULL;  //真正修改外部指针//(函数的形参需要是二级指针,如果使用的是一级指针,参数是值传递,在函数内部将ppcque置空,对外部指针无影响,外部指针将变为野指针)
}/*** @brief 判断循环队列是否为空** @param pcque 指向循环队列结构体的指针(需确保非NULL)* @return bool 返回true表示队列为空,false表示非空** @note 该函数实现循环队列的判空逻辑:*       1. 使用断言确保指针有效性(调试阶段捕获空指针)*       2. 直接比较队头指针(front)和队尾指针(rear)*       3. 当front == rear时判定为空队列*///3.实现:“循环队列的判空”操作
bool CQEmpty(CQ* pcque)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用//判满的核心逻辑:队尾指针和队头指针指向同一个位置return pcque->front == pcque->rear; //循环队列:空为true;非空为false
}/*** @brief 判断循环队列是否已满** @param pcque 指向循环队列结构体的指针* @return bool 返回true表示队列已满,false表示未满** @note 该函数实现循环队列的判满逻辑:*       1. 使用取模运算实现循环指针计算*       2. 通过(rear+1) % capacity == front判断队列满*       3. 预留一个空位区分队列空和满的状态** @details 循环队列判满的数学原理:* - 队列容量为capacity时,实际可以使用的是capacity-1个空间* - 当(rear+1) % capacity == front时:*   a) 若front == rear,队列为空*   b) 否则,队列已满* - 这样设计避免了使用额外标志位*/
//4.实现:“循环队列的判满”操作
bool CQFull(CQ* pcque)
{assert(pcque);//断言检查:确保队列指针有效,防止对空指针进行解引用//判满的核心逻辑:队尾指针的下一个位置(取模后)等于队头指针return (pcque->rear + 1) % (pcque->capacity) == pcque->front;  //循环队列:满为true;不满为false/* 示例说明:* 假设capacity=4(实际可使用的是3个位置):** 情况1:队列满*   front=0, rear=3*   (3+1)%4 = 0 == front → 满** 情况2:队列未满*   front=0, rear=1*   (1+1)%4 = 2 != front → 未满** 情况3:队列空*   front=0, rear=0*   (0+1)%4 = 1 != front → 未满(与判空条件区分)*/
}/*** @brief 向循环队列尾部插入一个元素** @param pcque 指向循环队列的指针(需确保非NULL)* @param x 要插入的元素值** @note 该函数执行以下操作:*       1. 检查队列指针有效性(调试阶段断言保护)*       2. 检查并扩容队列容量(通过CQCheckCapacity)*       3. 在队尾位置存入元素*       4. 更新队尾指针(实现循环移动)*/
//5.实现:“循环队列的入队”操作
void CQPush(CQ* pcque, CQDataType x)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用CQCheckCapacity(pcque);//1.将入队的元素的存储在动态数组中pcque->a[pcque->rear] = x;//2.将循环队列的尾指针向后移动pcque->rear++;//3.更新尾指针指向的正确的位置(处理越界的情况)pcque->rear = pcque->rear % (pcque->capacity);//4.更新当前循环队列中元素的数量pcque->size++;
}/*** @brief 从循环队列头部移除一个元素(出队操作)** @param pcque 指向循环队列的指针(需确保非NULL)** @note 该函数执行以下操作:*       1. 检查队列指针有效性(断言保护)*       2. 检查队列是否为空(空队列直接返回)*       3. 移动队头指针实现出队*       4. 处理指针越界(循环修正)*/
//6. 实现:“循环队列的出队”操作
void CQPop(CQ* pcque)
{assert(pcque);//断言检查:确保队列指针有效,防止对空指针进行解引用//情况1:循环队列为空if (CQEmpty(pcque)) return;//情况2:循环队列非空//1.将循环队列的头指针向后移动pcque->front++;//2.更新头指针指向正确的位置(处理越界的情况)pcque->front = pcque->front % (pcque->capacity);//3.更新当前循环队列中元素的数量pcque->size--;
}//7.实现:“循环队列的获取队头的元素”操作
CQDataType CQFront(CQ* pcque)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用//情况1:循环队列为空if (CQEmpty(pcque)) return -1;//情况2:循环队列非空return pcque->a[pcque->front];
}/*** @brief 获取循环队列的队尾元素** @param pcque 指向循环队列的指针(需确保非NULL)* @return CQDataType 返回队尾元素的值,队列为空时返回-1(需根据实际数据类型调整)** @note 该函数执行以下操作:*       1. 检查队列指针有效性(断言保护)*       2. 检查队列是否为空(空队列返回-1)*       3. 计算队尾元素的实际位置*       4. 返回队尾元素值*/
//8.实现:“循环队列的获取队尾的元素”操作
CQDataType CQRear(CQ* pcque)
{assert(pcque); //断言检查:确保队列指针有效,防止对空指针进行解引用//情况1:循环队列为空if (CQEmpty(pcque))  return -1;//情况2:循环队列非空//返回队尾的元素比返回队头的元素要复杂://原因:front指针指向的是队头的元素的位置;rear指针指向的是队尾的元素的后一个位置//怎么让队尾指针指向它的前一个位置?真的是pcirque->tail--;这么简单吗?//情况1:rear指向数组索引为0的位置(特殊情况-->rear应该指向的是capacity的位置,而不是数组下标为-1的位置)//情况2:rear指向数组索引的其他位置(正常情况)return pcque->a[(pcque->rear - 1 + pcque->capacity) % (pcque->capacity)];/* 关键计算:获取队尾元素的实际位置1. pcque->rear - 1 :理论上队尾元素在前一个位置2. + pcque->capacity :防止负数(当rear=0时)3. % pcque->capacity :确保结果在合法范围内示例:- 当capacity=5, rear=0时:(0-1+5)%5=4- 当capacity=5, rear=3时:(3-1+5)%5=2*/
}

这段代码通过数组模拟队列空间,利用取模运算让队列在逻辑上形成环形结构,解决了普通队列 “假溢出” 的问题,能高效完成入队和出队操作。

代码里用frontrear两个指针分别表示队头和队尾位置,通过(rear + 1) % capacity == front判断队列是否已满,用front == rear判断是否为空,还设计了扩容函数在队列满时自动扩展空间,同时有打印函数方便查看队列状态,整体实现了循环队列的基本功能和动态管理,让队列空间得到充分利用,操作也更高效。

上面的这段代码不仅是《数据结构初阶》系列的一个缩影,更体现了博主在梳理知识时的思考:如何用简洁的逻辑实现复杂的数据结构?如何通过注释和命名让代码更易读?

未来,博主还将在博客中分享更多类似的实战代码与解析,希望能帮助读者理解数据结构的底层逻辑,为进阶学习打下坚实基础。(如果你感觉这个博主还不错,对你有帮助的话,也可以关注一下博主,纪念日里也不会忘记宣传自己


憧憬

前面博主也提到过,博主的打算是本科直接就业,所以博主也一直在为这一目标默默奋斗。

但是在漫长的学习准备阶段,博主经常从网上听到类似的声音:“本科生找实习难于登天,仅有极少数人能成功,大部分学生只能落空” 和“C++ 岗位少之又少,本科生毕业根本找不到相关工作,学 C++ 等于‘毕业即失业’”和 “非 985、211 院校的学生就别碰 C++ 了,这门语言贴近底层,你们根本学不透,就算勉强学会,学历不够也会被筛掉”…… 诸如此类的言论,曾让博主心生疑虑:自己真的能找到实习吗?是否不该执着于 C++,转而去学 Java 会更好?

但在听取了 CSDN 上小伙伴的建议后,博主最终选择继续深耕 C++。毕竟 “打铁还需自身硬”,外界的声音或许反映了部分现实,但决定个人发展的核心始终是自身实力。或许 C++ 的就业形势并非一片坦途,但博主坚信,只要全力以赴、专注深耕,就一定能有所收获。

就业环境的好坏受社会周期影响,我们无法回到互联网行业的 “黄金时代”,我们唯一可以做的就是把握当下 —— 努力提升技术能力,在竞争中积累优势,为未来可能出现的机遇储备足够的底气。

正因为打算直接就业,所以博主必须提前找到实习,确保在秋招前至少拥有一段实习经历。因此,博主如今也是正在争分夺秒地学习,力求尽快完善技术栈,如同游戏中 “快速发育、点满技能点”,以便在未来的 “职场团战” 中更具竞争力。

不过,在加速学习的同时,博主也面临时间分配的挑战 —— 为了保证博客能按时创作出来,博主经常感觉到时间不够用。所以这一学期一些水课的平时分博主可能拿不到了,但是这个影响不大,请大家放心,博客更新绝不会中断。目前仍有大量知识内容待梳理,后续博主会将每周更新频率提升至 3 次,且会继续保持高质量输出,确保每一篇博文内容详实、干货满满。

好了,纪念日就纪念到这里吧,在此,想再和大家真诚地 “安利” 一番:

如果你目前还是学生,并且计划未来从事 C++ 相关方向的工作,强烈建议关注博主!博主后续分享的博客内容,将紧密围绕 C++ 就业所需的核心知识展开,涵盖 C++ 基础原理、数据结构与算法实战、操作系统底层逻辑、项目开发经验等关键领域。

即便现在,博主分享的内容与你的发展方向暂时不一致,也欢迎保持关注!博主始终相信,计算机技术的各个领域存在共通的底层逻辑与学习方法论。例如:数据结构的思维可迁移至任何编程语言,算法的优化思路能应用于各类场景。更何况,技术的发展日新月异,博主也会在深耕 C++ 的同时,持续探索其他领域,博主相信今后分享的内容一定会和你所在的领域不谋而合。

总之,关注博主不仅能获取当下所需的 C++ 就业干货,更能解锁一个长期陪伴的技术成长伙伴~

在这里插入图片描述

http://www.xdnf.cn/news/494425.html

相关文章:

  • 基于C#的MQTT通信实战:从EMQX搭建到发布订阅全解析
  • OpenResty 深度解析:构建高性能 Web 服务的终极方案
  • C语言_编译全攻略_从原理到实战的深度解析
  • 信息收集+初步漏洞打点
  • 完整卸载 Fabric Manager 的方法
  • JS 高级程序设计 设计模式
  • 【前端基础】10、CSS的伪元素(::first-line、::first-letter、::before、::after)【注:极简描述】
  • 前端面经13 JS设计模式
  • 分析 any 类型的利弊及替代方案
  • JAVA Spring MVC+Mybatis Spring MVC的工作流程*
  • 如何利用 Python 获取京东商品 SKU 信息接口详细说明
  • UE中的各种旋转
  • Linux服务器安全如何加固?禁用不必要的服务与端口如何操作?
  • uniapp -- uCharts 仪表盘刻度显示 0.9999999 这样的值问题处理。
  • 在Verilog中,逻辑右移(Logical Right Shift)和算术右移(Arithmetic Right Shift)的区别
  • Vue3 Element Plus 对话框加载实现
  • TensorRT10系列的api使用以及部署案例
  • jvm安全点(一)openjdk17 c++源码垃圾回收安全点信号函数处理线程阻塞
  • python四则运算计算器
  • Windows 上安装下载并配置 Apache Maven
  • JVM 机制
  • 学习笔记(C++篇)—— Day 6
  • 十二、Hive 函数
  • 数据湖与数据仓库融合:Hudi、Iceberg、Delta Lake 实践对比
  • JavaScript入门【3】面向对象
  • Bellman - Ford 算法与 SPFA 算法求解最短路径问题 ——从零开始的图论讲解(4)
  • Predict Podcast Listening Time-(回归+特征工程+xgb)
  • Git合并多个提交方法详解
  • C 语言学习笔记(数组)
  • WL-G4048 Multi-Port PCIe 4.0 Switch