自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(136)
  • 收藏
  • 关注

原创 C++的“引用”是条寄生虫

普通的变量是以“传值”的方式传递参数,需要将实参的值复制给形参,在函数中改变的是形参,而不是赋值给形参的实参。这就像我盖了一个和我的房子一模一样房子送给你,这个工程量是很大的,而且你装修是你的房子。引用在内部实现上也是用了指针的,但是用引用会更方便(语法层面,引用不需要用&获取地址,也不需用*访问数据)。指针以“传址”的方式传递参数,传过去的是地址,在函数中是能改变实参的。引用是以“传名”的方式传递参数,传过去的是变量的名字,在函数中也是能改变实参的。这就像我把我的房子的名字告诉你,你一样能找到我的房子。

2024-06-07 16:21:46 1036

原创 %n的作用

它在printf中不常用,但在scanf中有时很有用。当%n出现在scanf的格式字符串中时,它告诉scanf在成功读取并赋值给前面的变量后,将到目前为止读取的字符数(不包括任何由于空白字符、不可转换的字符或匹配失败而跳过的字符)存储在相应的指针所指向的int变量中。如果用户输入123abc,则num将被赋值为123,而char_count将被赋值为3(因为数字123包含3个字符)。%n用于在scanf中用于存储已读取的字符数。

2024-06-07 16:17:07 191

原创 运算符的重载

运算符重载实质上是一种特殊的函数重载,只不过这些函数的名字很特别,以“operator运算符”的形式命名,例如,operator+用于重载加法运算符,operator==用于重载等于运算符。这时便可应用重载,自己预先写好坐标相加的实现函数,然后就可以像浮点数相加一样使用+号计算两个坐标的相加值。当重载一个运算符时,你实际上在告诉编译器:“当这个运算符应用于老子的自定义类型时,得按老子写好的方式执行”。上面的代码有些地方可能不是很好懂,但应该可以大致看明白它是怎么实现运算符的重载的。

2024-06-06 18:12:34 454

原创 内置类型知多少?

整型:int、short、long、long long、unsigned int、unsigned short、unsigned long、unsigned long long 等。专有,作为变量的别名。严格来说它并不是一种数据类型,但其内部是用指针实现的,而且也不需要用户自定义,可以看作是一种内置类型。内置类型(也称为基本类型或原生类型)是C/C++本身定义的数据类型,它们直接由编译器支持,不需要用户自定义。通过enum关键字定义的,每个枚举成员通常都有一个内置的整数类型作为其底层类型。

2024-06-06 18:07:50 166

原创 函数的“重载”,全人工打造未解之谜

对敌人展开攻击时,装的机枪叫“射击”,装的大炮叫“开炮”,装的导弹叫“发射”,但你也可以都叫一个名字——“干它”。可能,为了去除这种味道,译者大刀阔斧地进行了改革,去其“超”,取其“多”,从而译成“重载(chóng zài)”(大多数人习惯叫chóng zǎi,这样更顺口,无伤大雅)。②副+动:over作副词,表“在上”,load作动词,表“装载”,overload指“在上面装载”,就是在一个东西上装这装那。通过重载,我们可以使用同一函数名实现不同的功能,相当于“一词多义”,在编程中称这个叫“多态性”。

2024-06-05 17:36:36 625

原创 字符的本质

因此,字符是一种特殊的整数,其数据类型为char,它实际存储的是字符的ASCII码,在语法上可以把字符当作int型使用。每一个字符都有一个整数编码,称为ASCII码。

2024-06-05 17:32:51 99

原创 正数、负数是一对反义词

大于0的数叫做正数(positive number),正数前加上符号“-” (负)的数叫做负数(negative number)如果一个问题中出现相反意义的量,我们可以用正数和负数分别表示它们。(语文里面有反义词,数学里有反义量)。有时,为了明确表达意义,在正数前面也加上“+” (正)号.例如,+3,+2。中国古代用算筹(表示数的工具)进行计算,红色算筹表示正数,黑色算筹表示负数。0既不是正数,也不是负数。

2024-06-04 17:42:55 177

原创 数是怎么产生的?

由衡量温度(零下一度、下降3度)、体重(减少1kg)、产量(减少2.7%)、收支(支出4.5元,亏空1.2元)、海拔(吐鲁番盆地的海拔为-155m)产生了负数。由表示“没有”(乞丐碗里一分钱都没有)“空位”(有位排队买彩票的大哥上厕所了),产生数0。由分物(两个人分一杯可乐)、测量(那东东3个和俺这根拐棍一样长)产生分数1/2,1/3。由记数(打了3条鱼)、排序(第3天打的鱼),产生数1,2,3,…数产生于人的生活和生产需要。

2024-06-04 17:28:36 372

原创 为什么叫“有理数”?

对应数学表示,A、B就是分子和分母,分号表示基于,A/B就是A基于B,这就是有理数的本质。因为是从5份中取3份,这里的每份的大小都是一样的。所以3和5天然存在一种“比例”关系,数学中的3/5表示的值正是被这样设计的,它表示3和5的比值,或者说3占5的多少比例,甚至也可以说3是5的多少倍。正如有了母亲才会有孩子一样,母亲就是孩子的生命的来源,是孩子的依靠,孩子是基于母亲而存在的。比如3/5,3是基于5而存在的,是5生出来的孩子。它的本质意思是这样的:把东西平均分成5份,取其3份。这就是“有理”的真正含义。

2024-06-03 14:30:58 299

原创 数的扩域方法

③增加小数点:小数(Decimal Numbers),如果小数点后增加不循环的数,就变成无理数(Irrational Numbers)。就好像两口之家生个娃就扩成三口之家,把爷爷奶奶接来变成三代同堂,娃以后再生个娃就变成四世同堂,以后继续深造便可千秋万代,一统江湖。数的扩域(Field Extension)指数域从一个较小的集合扩展到一个更大的集合的过程。有理数(Rational Numbers):整数和分数。实数(Real Numbers):有理数和无理数。整数(Integers):正整数、零和负整数。

2024-06-03 11:08:22 130

原创 标识符的分类

(5)预定义宏(也称内置宏):预定义宏是编译器预先定义好的宏,具备特定的功能,不需要用户使用#define定义就可以直接使用。(4)系统常量名:预先定义在头文件中的宏常量,通常为数学常量、物理常量或其他与特定库或框架相关的常量,如NULL(空指针)、M_PI(π)。预定义标识符和关键字的区别在于,用户可以重新定义预定义标识符另作他用,但这将失去预先定义的原意,所以不应随便更改这类标识符。标识符(identifier)是标识某个实体的符号,是程序员给变量、常量、函数、语句块等起的名字。

2024-05-24 17:35:41 1383

原创 语法检查、语义检查的区别

就像过安检,如果你带了大规模杀伤性武器,语法检查就会把你拿下,但如果你只是带个小孩儿,它就奈何不了你。可如果这个孩子一直哇哇大哭,狂喊救命,那么安检人员仍然可能将你拿下,这时候用的就是语义检查。比如标识符未定义(使用了未定义的变量、函数),函数未被正确调用(参数数量、类型和顺序与函数声明不符),以及存在未定义的行为(除以零、数组越界)。语义检查是语法检查之后进行的更高级别的检查。它关注代码的含义,检查的是逻辑。语法检查是第一道检查,就像英语的语法一样,它检查的是存不存在语法错语。

2024-05-24 17:07:22 270

原创 什么是标识符

简单来说,标识符(identifier)就是标识某个实体的符号。它是程序员给变量、常量、函数、语句块等起的名字。

2024-05-23 17:51:03 108

原创 LLMs的简单科普

这个“大”字才是模型的核心,威力的体现,其参数动辄十几亿甚至上万亿。首先,它是一个语言模型,是现代自然语言处理(Natural Language Processing, NLP)领域的核心组成部分,能够处理和理解大量的文本数据,并生成新的、有意义的文本。通俗地讲,就像看书一样,以前是按顺序逐字逐句地读(循环神经网络RNN就类似这种玩法),现在一目十行,而且眼睛会自动关注那些最有价值的信息,这是一种自动注意的能力,就叫“自注意力”。分析文本中的情感倾向,判断文本是积极的、消极的还是中性的。

2024-05-23 17:33:34 721

原创 C语言布尔类型的前世今生

正常布尔类型只占1个字节(这其实也是bool类型的一个存在价值,占用内存比int型小),但因为bool被替换为int,所以sizeof(bool)输出的是4个字节。因为#define bool int的存在,在编译时会自动将所有的bool替换为int,相当于这个新设的bool类型完全没起作用。只是这个布尔类型不是像bool、BOOL这样的美男子,而是这样一个怪胎:_Bool。从此以后,我们不用自己造炮了,只要加上头文件,就可以像其他语言一样使用bool、true、false。

2024-05-21 16:44:36 580

原创 “移动”问题的算法原则

像绘图、走笔、蛇形填数等问题都会涉及到移动,这类问题的移动原则:先判断,再移动。不要走一步后发现越界了再退回来。先判断,再移动,就能避免无谓的移动导致的后退操作。所以,在很多情况下,最好是在做一件事之前检查是不是可以做,而不要做完再后悔。因为“悔棋”往往比较麻烦。这和现实生活也很相像,我们总说做事要三思而行。

2024-05-21 16:09:18 108

原创 字符串的周期:每一期都有那么几位

首先依次遍历第1个周期内的k个字符s[i](i=0~k-1),然后按纵向扫描的方式让后面每个周期内的对应的字符都与第1个周期内的字符一一比较,但凡遇到一个不相等的(即s[i+n*k]!),就判定k不是s的周期,从而将判断是否为周期的标志变量flag置为0。本代码有三层循环,第一层是周期k的遍历,第二层是第一个周期内字符的遍历,第三层循环是以k为公差的等差数列j的遍历。题目明确说明以长度为k的字符串重复多次得到字符串s,则称s以k为周期,所以字符串的长度len必然是k的倍数,据此可跳过不满足此条件的k。

2024-05-20 18:25:10 1075

原创 算法竞赛最关注的是什么?

所以,我们的目标是解决问题,而不是展示编程技巧,应保持简单(Keep It Simple and Stupid,KISS)。多数算法竞赛采用黑盒测试,即只考查程序解决问题的能力。它只关注结果,而不关心采用了什么方法。记住:算法竞赛是在比谁能更好地解决问题,而不是在比谁写的程序看上去更高级。相反,即便你造出满天星光,结果少了一个空行,也是悲剧收场。只要时间不超限,哪怕你用的方法再笨,结果正确就OK。

2024-05-20 18:20:22 91

原创 统计数列中的数字出现次数

关于f[n+1][k]=f[n][k]+x的实现,老金最初也想用一个表达式实现,但是没有成功,只好退而求其次先用一个循环实现f[n+1][k]=f[n][k],不知道有没有高手有更好的方法,还望指点一二。更高效的做法是一次性从1-10000整个遍历一次,针对每个n,分别求出0-9出现的次数,然后把这些数据都存储到数组中。这时候就需要用到二维数组f[n][k]统计数次,n表示前n个整数,k表示0-9。显然有f[n+1][k]=f[n][k]+x(x是k在整数n+1中出现的次数)如想进一步了解详见“

2024-05-18 11:55:05 758

原创 竞赛程序只做三件事

不要打印诸如“请输入××○○”的诱惑性提示信息,不要用武力威胁等方式强迫计算机计算,不要在打印输出后“让程序停一会儿”,更不要尝试画图、访问网络、偷看小说等与算法无关的事情。算法竞赛的程序应当只做三件事情:读入数据、计算结果、打印输出。

2024-05-18 11:42:36 65

原创 常见的C编译器

这些编译器都有自己的特点和优点,适用于不同的应用场景。例如,Microsoft Visual C++适用于Windows系统,其语法高亮和括号补全功能强大,但体积较大;而GCC和Clang则适用于多种操作系统,包括Linux、macOS和Windows等,其生成的代码执行效率较高,但配置相对复杂。选择合适的编译器对于开发效率和代码质量至关重要。常见的C编译器有Microsoft Visual C++、GCC、Clang和Intel C++ Compiler等。

2024-05-17 18:00:56 67

原创 一文搞定“宏”

它用于宏定义中的替换列表中,会把其后的宏参数转换为一个用双引号(quotes)括起来的字符串。宏替换就是简单的文本替换,它是在编译阶段完成的(相当于Word里的查找替换),因此它在执行时不需要函数调用的开销:传递参数和返回值等,所以宏比函数在程序的内存开销和速度方面更胜一筹。需要注意的是,如果类函数宏的参数含有逗号,逗号只会被识别为参数的分隔符(separator),而不会被识别为逗号操作符。①条件判断(x++)>( y++),结果:x++表达式的值为3,y++表达式的值为7,x=4,y=8。

2024-05-17 17:47:39 1487

原创 如何打印指针?

注意:在将指针传递给%p时,通常需要将指针转换为(void *)类型,尽管在C99及更高版本中,这不是必需的,但在旧版本的C和C++中,这是必要的。当你需要打印指针的值时,应该始终使用%p,而不是使用%x或%u等,因为%p知道如何正确处理指针的大小和可能的对齐要求。%p用于打印指针的值。以十六进制的形式输出,并在前面加上0x或类似的前缀。

2024-05-16 17:37:25 295

原创 void类型的用途

但是我们可以将任何一个表达式(当然也包括变量,变量也是表达式)强制转换为void类型。指针是一个通用指针,可以指向任何类型的数据,但它本身并不含有其所指向数据的具体类型信息。因此,当想要访问它所指向的数据时,我们需要将其转换为特定类型的指针。如果强行省略,编译器会默认返回一个int类型的值,这可能会导致未定义的行为。在C语言中,void 是一个特殊的类型,它表示“无类型”或“空类型”。注意,不能将一个变量定义为void类型,因为void本质上表示没有类型,用来声明变量没有实际意义。也可以用作指针的类型。

2024-05-16 17:04:59 376

原创 什么是标志变量?

还有一些is+变量名,比如isFinished(是否完成)、isVisible(是否可见)、isValid(是否有效)、isChecked(是否选中)、isEnabled(是否启用)。标志变量是一个在程序设计中常用的概念,主要用于表示某种状态或条件是否成立。通常,标志变量是一个布尔类型的变量,即其值只能是真或假。最常用的标志变量名为flag,因为标志变量的英文名就是flag variable。比如,用标志变量表示玩家是否通关,用户是否点击了某个按钮。

2024-05-15 17:45:57 373 1

原创 不干人事的表达式:(void)0

它想对世界表达的不是“我是这样一个类型”,而是“我什么类型都不是”。(void)就像(int)一样,表示强制类型转换,后面的0是一个整型数。这是一个宏替换,它定义了一个名为 assert 的宏,它接受一个参数_Expression。也就是说,它是为调试而生的,显然不应该让调试产生的值影响正式代码的运行。这就是要生成表达式的原因,而0是最简单的表达式,不用它还用谁呢?这时候(void)这把圆月弯刀就派上用场了,因为强制转为void型,表达式没了返回值,因此不能赋给任何变量,也不能做任何函数的参数。

2024-05-15 17:21:20 721

原创 程序员就是管道工

剩下的就是修建管道了,你要知道各种管的型号、用途,然后把它们一节节连在一起,最后测试水流,维修漏点,这好比编程。因此,可以这么说,数据就是水,指令就是管道,程序就是水流,算法就是管道的设计方法,编程就是修建管道。要想让水高效地流向我们想要的地方,就要设计一个精良的管道系统,这好比算法。指令是按照特定的顺序执行的,这些顺序好比水的流向。这么说来,我们程序员,其实就是管道工。程序是由指令和数据组成的。

2024-05-14 16:41:42 286

原创 捕捉错误的assert

而在<assert.h>中会通过条件编译检测NDEBUG有没有定义,如果定义了这个宏,就废了assert,没定义的就让它正常执行。不用理解代码具体的意思(无非表达的就是定义了NDEBUG怎样怎样,没定义又怎样怎样),只要明白它用条件编译来判断是否定义了NDEBUG,所以如果将#define NDEBUG写在后面,当然就会视为没有定义。在程序中,如果定义了NDEBUG 宏,那么 assert 宏就会被禁用,所有的 assert 调用都会被忽略。那回头再想输出调试结果怎么办?

2024-05-14 14:29:18 265

原创 化学式的分子量计算——字符转数字

就是数字结束时,或者说是遇到下一个字母时。比如C12,可以先将字符转化为对应的数字(字符的ASCII码值-48),然后用1*10+2算出这个两位数字的大小,最后再将1。代码中再次用数组W[256]实现了查找表,这样可以通过将字母设为数组的下标,元素值设为原子量的值,从而快速获取字母对应的原子量。无数字时代表只有一个原子,因此可以设原子数n的默认值为1,当有数字时,计算数字并更新n。b. 计数时,如果n=-1,说明其前一位是个字母,此位数字是第一个数字,据此将n的初始值置为0,以便后续使用“连乘加法”计数。

2024-05-13 18:10:32 1145

原创 什么是表达式?

表达式是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。在C/C++中,表达式可以是变量、常量、函数调用、算术运算等,它们的共性是都可以产生或计算出一个值。也就是说,哪怕3.14这样的单独数字,也是一个表达式,这个叫“常量表达式”。简单来说,表达式就是为了得到某个值而进行的数字、字母和算符的组合。

2024-05-13 18:02:55 238

原创 scanf留下的那一片云彩

注意,因为要返回自加后的值,此时就需要用++cnt,不能用cnt++(关于二者的区别参见“找不到北的i++”一文https://blog.csdn.net/jjmhx/article/details/136995419)。思路就是对输入串的字符进行遍历,如果遇到“O”就cnt++,如果遇到“X”就将cnt重置为0,然后每次将cnt加到sum中即可。老金想着秀一下“编技”,打一开始就想用getchar读取字符,这样就用不着数组了,没想到输出了意想不到的结果。②累加器sum,用于计算串的得分。

2024-05-11 18:12:02 1360

原创 “计数器”的划时代发明

计数器用来统计事件发生的次数。在编程时,将count或cnt作为计数器变量是一个好习惯,这样能提高代码的可读性。以前“数羊”需要用脑默数,人反而可能会更清醒。有了数羊机,大脑可以完全得到解放,迅速进入空灵状态,实现快速入睡。计数器有很多实际用处,比如,为了帮助失眠人士,咱们可以发明一个“数羊机”。数羊时只需轻轻动动手指,如抚琴一样,音乐的节拍在指尖自由地流淌。如果您已成功入睡,只需要点下回车键,就是这么简单!相信有了我们的陪伴,有一天您能“一键入眠”!数羊机会为您自动记录数羊次数,永久存档。

2024-05-11 17:59:26 136

原创 程序找茬:统计字符个数问题

所以写不写都是一样,但不写的话一般会被认为对代码清晰性有影响(其实也影响不了啥清晰性,说白了就是大家都加,你不加你就是异类,让人看了心生违和感)。因此,if(s[i] == 1) 是错误的,应改为:if(s[i] == '1')。将计算字符串长度的函数strlen(s)写在循环中,会导致函数的重复调用,即每进行一次循环条件判断,都要重新计算字符串s的长度,显然这样会造成效率低下。我们在后续编程时应注意:如果函数的返回值是确定的,不要将其放在循环中,而应预先将其值存入变量。不过即便不影响运行,还是加上为好。

2024-05-10 17:29:05 506

原创 潇洒哥“伪代码”

伪代码的核心优势在于其没有限制。只要能清晰地表达算法的逻辑,可以信马由缰、潇潇洒洒、不拘一格地使用伪代码。不必担心语法错误、不受语言规则限制。把这样“不是真正程序”的“代码”称为伪代码(pseudocode)。伪代码的主要作用是描述算法逻辑,避开细节,启发思路。可笑的是,伪代码还有一些正规的定义和使用规则,这完全有悖初衷,实属没有必要。

2024-05-10 15:16:38 98

原创 使用数组的必要条件

每输入一个数后,只能计算出当前输入所有数的平均值,而公式中的平均值是输入完成后所有数的平均值,所以“数据值-平均值”的值与以后输入的数有关,无法在每输入一个数更新此值,因此需要数组。假设输入只能读一遍。每输入一个数,只需要将其与max、smax比较即可算出新的max、smax,与以前输入的数无关,所以可以不用数组。可以在每次循环时更新4个变量的值:最大值、最小值、数的和、数的个数,这些值都只与原值和最近一次输入的数有关,所以可不用数组。输入数的个数只与原个数和最近一次输入的数有关,因此可以不用数组。

2024-05-09 18:00:58 428

原创 scanf、printf函数对字符串的各种搞法

scanf("%s", s)”和“scanf("%d", &n)”类似,它会读入一个不含空格、TAB和回车符的字符串,存入字符数组s。注意,不是“scanf("%s", &s)”,s前面没有“&”符号,因为s本身就指向了内存地址。如果是字符串数组chars[maxn] [maxl],可以用“scanf("%s", s[i])”读取第i个字符串。

2024-05-09 17:33:30 216

原创 负数在计算机内的编码

我们知道,n位二进制数能表示的数的个数肯定是偶数个(2的n次方),既然只有一个0,那正数和负数的个数肯定是不相等的(个数和为2^n-1)。比如8位二进制数能表示的数有256个,除去一个0,还剩255个。正0的补码是原码本身(没有加1),负0的补码是原码的反码加1(有加1),所以二者之和不可能是0,即00000000+10000000不等于0,所以补码10000000肯定不再表示0。所以,10000001-1=10000000,这个结果正是前面讨论的-0的补码,它应该表示-128,这个数就是最小的负数。

2024-05-08 17:27:13 877

原创 字符串的赋值

虽然看上去是将整个字符串赋给了数组,其实就是一种赋值方式的简化,本质上还是把一个个字符存入数组。和数组一样天生低人一等,给字符串变量赋值时,只有初始化时才可以使用“=”,之后均需使用strcpy()函数。因为字符串本质上就是数组,因此它的赋值也具有数组的特点:只能在初始化时用等号。

2024-05-08 16:55:12 404

原创 移位运算符的数学应用

如果你左移一个无符号整数,并且移动的位数超过了该整数类型可以表示的位数,那么结果将是未定义的(在大多数情况下,这会导致“环绕”行为,即最高位被丢弃,最低位被新位填充)。如果你左移一个有符号整数,并且移动的位数超过了该整数类型可以表示的位数减1(因为符号位通常占用一位),那么结果也是未定义的。规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是 移动66次和移动2次得到的结果相同。

2024-05-07 17:55:58 328

原创 移位运算符的优先级

比如在二进制中,8位最大整数就是8个1,即2^8-1,用左移运算符“<<”写出来就是(1<<8)-1。,因为“<<”运算符的优先级没有减法高,括号是必需的。移位运算符分为左移<<、右移>>,它属于位操作符,即在二进制位级别上进行操作的运算符。5个双目位操作符的优先级顺序为:左移<<、右移>>→按位与&→按位异或^→按位或|。位操作符除了一个单目运算符(按位取反运算符~)外,优先级都低于加减运算符。左移n位就相当于乘以2的n次方,右移n位相当于除以2的n次方。

2024-05-07 17:52:11 449

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除