- 博客(114)
- 收藏
- 关注
原创 【C语言】预处理
C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。__FILE__ //进⾏编译的源⽂件__LINE__ //⽂件当前的⾏号__DATE__ //⽂件被编译的⽇期__TIME__ //⽂件被编译的时间__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义1000register//为 register这个关键字,创建⼀个简短的名字for;;//⽤更形象的符号来替换⼀种实现break;case。
2024-10-05 22:00:13 1060 1
原创 【C语言】编译和链接
我们在 test.c 文件中每一次使用 Add 函数和 g_val 的时候必须确切的知道 Add 和 g_val 的地址,但是由于每个文件是单独编译的,在编译器编译 test.c 的时候并不知道 Add 函数和 g_val变量的地址,所以暂时把调用 Add 的指令的目标地址和 g_val 的地址搁置。比如:目标文件的格式elf,链接底层实现中的空间与地址分配,符号解析和重定位等,如果你有兴趣,可以看《程序的自我修养》⼀书来详细了解。链接是一个复杂的过程,链接的时候需要把一堆⽂件链接在一起才生成可执行程序。
2024-10-05 19:51:06 899
原创 【C语言】指针详解(三)
所以,根据数组名是数组首元素的地址这个规则,二维数组的数组名表示的就是第一行的地址,是一维数组的地址。根据上面的例子,第一行的一维数组的类型就是 int [5] ,所以第一行的地址的类型就是数组指针类型。那就意味着二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址,那么形参也是可以写成指针形式的。确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名 的方式获得函数的地址。那数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。
2024-10-04 22:43:15 708
原创 【C语言】指针详解(二)
数组是可以传递给函数的,首先从一个问题开始,我们之前都是在函数外部计算数组的元素个数,那我们可以把函数传给一个函数后,函数内部求数组的元素个数吗?这里我们使用 &arr[0] 的方式拿到了数组第一个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址,我们来做个测试。,数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
2024-10-04 18:46:44 1077
原创 【C语言】指针详解(一)
就是为了不能被修改,如果p拿到n的地址就能修改n,这样就打破了const的限制,这是不合理的,所以应该让p拿到n的地址也不能修改n,那接下来怎么做呢?如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL.NULL 是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错。代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n就行修改,就不符合语法规则,就报错,致使没法直接修改n。
2024-09-30 22:36:47 1437
原创 【C语言】操作符
即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一计算路径,那这个表达式就是存在潜在风险的,建议不要写出特别负责的表达式。有问题请指出,大家一起进步!!!
2024-09-29 22:41:47 919 1
原创 【C语言】函数递归
把Print(1234) 打印1234每一位,拆解为首先Print(123)打印123的每一位,再打印得到的4 ,把Print(123) 打印123每一位,拆解为首先Print(12)打印12的每一位,再打印得到的3,直到Print打印的是一位数,直接打印就行。当我们n输⼊为50的时候,需要很长时间才能算出结果,这个计算所花费的时间,是我们很难接受的,这也说明递归的写法是非常低效的,那是为什么呢?再稍微分析一下,当 n<=1 的时候,n的阶乘是1,其余n的阶乘都是可以通过上述公式计算。
2024-09-28 21:44:43 919 1
原创 【C语言】VS调试
bug本意是昆虫”或“虫子”,现在一般是指在电脑系统或程序中,隐藏着的一些未被发现的缺陷或问题,简称程序漏洞。“Bug”的创始⼈格蕾丝·赫柏(Grace Murray Hopper),她是一位为美国海军⼯作的电脑专家,1947年9月9日,格蕾丝·赫柏对Harvard Mark II设置好17000个继电器进行编程后,技术人员正在进行整机运行时,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高电压击死。
2024-09-27 20:59:15 771
原创 【C语言】函数
了解了库函数,我们的关注度应该聚焦在自定义函数上,自定义函数其实更加重要,也能给程序员写代码更多的创造性。⼀般我们在使用函数的时候,直接将函数写出来就使用了。//判断⼀年是不是闰年int is_leap_year(int y)//函数的定义return 1;//函数的调⽤printf("闰年\n");elseprintf("⾮闰年\n");return 0;函数的定义在函数调用之前,没啥问题.int main()
2024-09-26 23:17:12 874 2
原创 【C语言】数组
有一个比较迷惑的点,变长数组的意思是数组的大小是可以使用变量来指定的,在程序运行的时候,根据变量的大小来指定数组的元素个数,而不是说数组的大小是可变的。数组的大小一旦确定就不能再变化了。前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们**把一维数组做为数组的元素,这时候就是二维数组,**二维数组作为数组元素的数组被称为三维数组,二维数组以上的数组统称为多维数组。绿色的数字表示行号,第⼀行蓝色的数字表示列号,都是从0开始的,比如,我们说:第2行,第4列,快速就能定位出7。
2024-09-25 22:06:48 1145
原创 【C语言】猜数字游戏
前面学习的这些知识,我们就可以写一些稍微有趣的代码了,这里就来写一个猜数字游戏。电脑自动生成1~100的随机数玩家猜数字,猜数字的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束。
2024-09-24 21:29:17 1039 3
原创 【C语言】分支和循环
C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构,C语言是能够实现这三种结构的,其实我们如果仔细分析,我们日常所见的事情都可以拆分为这三种结构或者这三种结构的组合。我们可以使用if 、 switch 实现分支结构,使用for 、 while 、 do while 实现循环结构。
2024-09-23 22:20:10 919 1
原创 【C语言】数据类型和变量
printf() 的作⽤是将参数文本输出到屏幕。它名字里面的 f 代表 format (格式化),表示可以定制输出文本的格式。return 0;上面命令会在屏幕上输出一行文字“HelloWorld”。printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n。return 0;return 0;printf()是在标准库的头文件stdio.h定义的。
2024-09-21 21:15:16 730 1
原创 【C语言】常见的C语言概念
人和人交流使用的是自然语言,就像是汉语、英语、日语。那人和计算机是怎么交流的呢?使用计算机语言。目前已知已经有上千种计算机语言,人们们是通过计算机语言写的程序,给计算机下达指令,让计算机工作的。C语言就是众多计算机语言中的⼀种,当然C++/Java/Go/Python都是计算机语言。在VS上写代码,我们是需要创建项目的,直接新建项目就可以了。在项目中就可以添加源文件和头文件。C语言把 .c 为后缀的文件称为源文件,把 .h 为后缀的文件称为头文件。
2024-09-19 12:27:10 3415 2
原创 【C++】多态
不同的人做同一件事情,多种形态,结果是不一样的。多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写(要求三同,三同指的是:函数名、参数、返回值)public:virtual void BuyTicket() { cout << "Person->买票-全价" << endl;
2024-04-23 15:35:28 2398 47
原创 【Linux】地址空间&&虚拟地址
然后把修改之前的数据拷贝到新空间中,再把新的物理地址和之前的物理地址相比较,把新的物理地址放在子进程的页表中,重新构建映射,页表的右侧就指向新的物理地址空间,这个工作结束,才会就行让子进程执行写入操作,把100改为300。假设在物理内存上存放一个全局变量g_val,默认内容是100,g_val在页表在地址空间中都要被找到,所以在地址空间的初始化数据中就有它的地址虚拟地址,页表的左侧也有它的虚拟地址,在页表右侧就有它对应的物理地址。修改的只是子进程的物理地址和页表,而地址空间里面的依然是虚拟地址。
2024-04-19 17:16:12 1414 30
原创 【算法】分治-归并
在左边的cur1位置的值如果大于右边cur2位置的值,说明cur1值和它之后的值都是大于cur2的,那么此是就有mid-cur1+1个逆序对,然后再比较cur1值和cur2++之后的值,看看能不能构成逆序对,能够成的话就又有mid-cur1+1个逆序对了。而左边排序又是找一个中间点,把左边排好序,直到这个左边就行一个值,那么就返回,左边和右边排好,再把这两个有序数组合并,再向上返回,直到整个数组都有序。也是按照中间元素划分区间,先计算左右两侧的翻转对,再计算翻转对的数量,就是再排好序。
2024-04-18 16:28:16 971 5
原创 【C++】继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。举个例子:在学校里面要定义教师类和学生类还有宿管、保安这些类,他们里面都有的成员变量写在了多个类里面就会显得代码冗余,此时就可以用到继承。
2024-04-18 08:34:11 1380 6
原创 【C++】priority_queue&&priority_queue模拟实现
优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。
2024-04-17 08:39:16 1370 12
原创 【Linux】进程的优先级&&环境变量
上一篇在进程中提到了【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,这次来继续来谈进程。在进程的PCB中存在一个进程的优先级,那么什么是进程的优先级?进程的优先级就是指定一个进程获取某种资源的顺序。进程中使用task_struct进程控制块结构体中的内部字段用一个整型prio表示优先级。Linux中优先级数字越小,优先级越高。比较一下优先级和权限:权限决定一件事能不能做,而有优先级就表示一件事情能做只是代表获取资源的顺序。
2024-04-16 10:35:45 1962 50
原创 【算法】字符串
模拟的竖式计算的步骤,如果相加等于2,那么就进1,然后将这个字符取模就加到要返回的结果中,一直到两个字符串都结束。利用中心扩展算法,固定完中间位置后,用两个指针一个在走左边,一个走右边,如果两个指针执行的字符是一样的,就移动,一直到指针指向的字符不同,或者一个指针越界。如果直接按照竖式计算来的话,思路是很简单的,但是代码不容易写,得处理进位和高位相乘要补上0,还得处理前导0和计算顺序,很多细节。把每一个位置的值相乘之后,先不进位,把每次计算的结果放在一个数组里面,最后再来处理进位。
2024-04-15 08:21:16 816 24
原创 【算法】bfs解决FloodFill问题
以例2模拟:从(0,0)位置开始扩展,不能扩展回去,为了不在原数组上面修改,可以给一个bool数组和原矩阵规模是一样的,然后里面如果存false,就代表这个位置没有遍历过,如果存true表示遍历过。第三层从(0,2)、(2,0)和(3,1)开始:(0,2)多加了(0,3);(3,1)多了(3,2)假设有这么一个矩阵,给的位置是(1,1)与(1,1)相连的所有像素相同的点,全部修改为2。第二层从(1,2)和(2,1)开始:(1,2)的扫描多加了(0,2);(2,1)的扫描多了(2,0)和(3,1)
2024-04-13 09:00:00 978 10
原创 【算法】模拟
模拟算法就是根据题目所给的照葫芦画瓢。考察的是代码能力。步骤:1.模拟算法流程(一定得自己先过一遍流程)2.把流程转化为代码。
2024-04-12 08:31:49 1342 6
原创 【算法】哈希表
只有小写字母,只需要开26个大小的数组,只统计s1中每个字符出现的个数就行,来遍历s2时候在哈希表中出现对应的字符就减掉1就可以,只要哈希表里面全部为0就可以,但如果s2中出现的某一个字符,在哈希表里面被减成了负数,就直接返回false就可以。但是可能会出现一个情况,出现相同的元素,但是下标不一样,可能会吧哈希表里面的值覆盖掉,可题目中找的是小于等于某一个值,所以就直接找最近的值,所以是可以覆盖掉哈希表之前相同的值。但这样的方式来用哈希表优化,可能就会出现某一个数被找了两次,还得再判断一下,就比较麻烦。
2024-04-11 14:50:08 1380 9
原创 【算法】位运算
把这些元素按32位位图存起来,重复3次的数位图的最后一位是0或者1,出现一次的数位图最后一位也是0或者1,它们这个位图这个位置的和就是0、1、3n、3n+1。把所以数的所以对应位置位图都加起来,在模上3,就得到出现一次数那个位置得位图是0还是1,是0就修改为0,是1就修改为1,然后以此类推,把这32个比特位全部修改完毕。因为两个数字是不相同的,那么它们的二进制位置上遇到有个位置是1,就可以将数据分为两部分,一部分是位置是1的,一部分不是。就像前面消失的数字一样,可以先做异或操作把消失的两个数字先取出来。
2024-04-11 08:06:42 974 10
原创 【算法】双指针算法
这里是三个数的和,可以先固定一个数a,仅想要保证这个a是小于0就行(在后面等于0相加的值不可能等于0),然后在该数后面的区间内,利用双指针算法,快速找到两个数的和,者两个数的和是a的相反数,这样这三个数相加的时候,值就为0。定义两个快慢指针,用平方和来充当指针,slow指向第一个数,fast指向第二个数,如果这两个指针一直不相等,就一直循环,slow走一步,fast走两步。题目中所说最后的平方和为1才是快乐数,如果不为1,就一直循环,其实可以看成两个都是循环,一个一直循环的是1,另一个循环的值都不相同。
2024-04-10 08:13:16 1184 7
原创 【算法】二分算法题
寻找左边界:我们注意到以左边界划分的两个区间的特点:左边区间 [left, resLeft - 1] 都是小于x 的;右边区间(包括左边界) [resLeft, right] 都是等于等于 x 的;因此,关于 mid 的落点,我们可以分为下面两种情况:◦ 当我们的 mid 落在 [left, resLeft - 1] 区间的时候,也就是 arr[mid] < target。
2024-04-09 21:13:04 963 10
原创 【算法】贪心算法练习一
一、贪心策略:解决问题的策略,局部最优->全局最优把解决问题的过程分为若干步;解决每一步的时候,都选择当前看起来“最优的”解法;希望得到全局最优。二、贪心策略的正确性因为有可能“贪心策略”是一个错误的方法正确的贪心策略,是需要证明的常见的证明方法就是在数学中见过的所有证明方法。三、学习贪心算法的方向遇到不会的贪心题,很正常,把心态放平。前期学习的时候,把重点放在贪心的策略上,把这个策略当做经验吸收。如何证明贪心策略是正确的。
2024-04-09 08:09:15 888 10
原创 【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行
上一篇博客中提到【Linux】进程初步理解,这次继续来分享与进程有关的知识。
2024-04-08 08:41:05 802 10
原创 【OJ】stack刷题
在没有遇到第一个算符之前,就把数据入栈,当遇到运算符,就把它前面两个数2和1出,计算出来结果就是2+1=3,然后再把这个3再入栈;当再一次遇到表达式时候,又把它的前面两个数出栈做对应的运算之后,在把算出的结果入栈,最后输出栈顶元素就可以了。因为再删除数据的时候,当a栈顶出栈的时候,_min栈顶同时也得出栈,这样才能保证_min.top()里面能够保存的是最小值。先把入栈序列入栈,如果出现入栈序列和出栈序列的栈顶元素相同,那么两边就同时出数据,直到入栈序列和出栈序列的栈顶元素不匹配,或者出栈序列为空。
2024-04-07 08:45:37 894 25
原创 【Linux】进程初步理解
如果操作系统要直接把硬件管理好,前提是得有通信,所以操作系统得访问到硬件,可、是每一种硬件的物理特性是不一样的,如果直接由操作系统来直接访问下面的这些硬件,如果硬件的物理特性发生了变化,还得去改操作系统。到朋友电脑那边,被朋友收到的输入设备肯定也是网卡,然后这个数据就传到内存里,而QQ要做解密的操作,所以数据得加载到CPU中,消息解密得到“你好”,再写到内存中,然后再把消息刷新到输出设备显示器上。把所有进程用struct PCB* next指针连接,管理起来,所以对进程的管理,就变成了对链表的增删改查。
2024-04-06 17:31:08 1699 32
原创 【OJ】动规练习七之【模板】01背包
第二种情况:选择i物品,那么必须有w[i],实现的价值最大,就得从i-1里面挑价值最大的出来,并且此时体积要改变,所以到这里的体积必须能够装下v[i],到i-1位置体积就必须小于j-v[i],但是这里必须判断dp[i][j]是不是等于-1,所以这里的状态表示就是dp[i][j]不是等于-1情况下w[i]+dp[i-1][j-v[i]]第一种情况:不选择i物品,那么就是在i-1里面选择,并且体积也依旧小于j,所以就是dp[i-1][j]它依赖它的上一行位置,i-1表示的是上一行,从上往下。
2024-04-05 22:35:41 1112 10
原创 【C++】stack和queue
stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:empty:判空操作back:获取尾部元素操作push_back:尾部插入元素操作。
2024-04-05 20:50:13 1151 17
原创 【Linux】Linux调试器-gdb使用
在前面的博客【Linux】编译器-gcc/g++使用已经分享了关于编译器的使用,而编译器的使用离不开调试,这次就来分享一下Linux调试器-gdb使用。
2024-04-03 17:11:04 1794 16
原创 【C++】list介绍
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
2024-04-01 09:38:38 1818 32
原创 【OJ】动归练习五之子组串
另一种情况就是不止一个数就是i-1最小的子数组乘积f[i-1]乘i位置对应的nums[i],但是这里的nums[i]可能是小于0,所以这里还得分两种情况:一个是nums[i]>0,那么就是最小的子数组乘积g[i-1]乘i位置对应的nums[i];然后取这两种情况的最小值。另一种情况就是不止一个数就是i-1最大的子数组乘积为负数的最长长度,如果num[i]>0,长度就为就是以i-1为结尾的子数组乘积为负数的最长长度再加1,也不能直接加一,先判断判断g[i-1]是否等于0,是就是0,不是就取g[i-1]+1;
2024-03-30 11:29:37 1346 20
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人