为什么很多程序员觉得自己平时只是条条 a p i, 一 到 ai 时代就慌得不行?因为底层逻辑不扎实,所谓的十年经验,不过是把一年的经验机械地重复了十年。如果你正陷入这种技术平庸的瓶颈,这本被誉为全球 c 加加开发者甚经的 c 加加程序设计语言第四版二零二六最新重一本,就是你迟早得去读的那本内攻心法。 别急着说 c 加加过时了,二零二六年的今天,顶尖金融公司每秒亿万次的高频交易系统,你手机里那些虚幻引擎打造的三 a 大 作,还有正在重塑世界的大模型 ai 底层算子调度这些真正高新的核心架构代码库里, c 加加占比超过六成。这本书第四版的重磅之处,是彻底讲透了 c 加加十一这一划时代标准。 它不是那种教你怎么调 a p i。 的 速成手册,它讲的是编程思想和体系。很多人代码内存泄露并发卡死,花大价钱买各种速成课,却不知道梳理 r a i i。 资源管理和智能纸质那一张,早就把答案写清楚了。你看完会明白,真正的编程不是乱拳打死老师傅,而是一招一式皆有杀招。 一本顶三本,既是新手的正确入门指南,也是老手查漏补缺的案头权威手册。技术领域会不断淘汰手里只有 a p i。 锤子的人,但永远在重金寻找深刻、懂底层、懂性能的 c 加加工匠带你读好书,从底层彻底看透技术人生。
粉丝4805获赞4.3万

大家好,欢迎来到博兴教育,我是天狼。第二十三讲条件判断、 if 以及 本节课主要是带着大家来学习 if 以及的三种形式。首先我们来看第一种形式, if 后面跟着一个什么呢?判断条件,这个表达式 后面跟着的是语句框,但是他的执行过程是怎么样的呢?首先他要判断这个条件是否成立, 如果判断条件它成立,就会执行后面的语句块,否则就跳过这个语句块了。现在我们看一下它这个流程图,先是进行判断条件, 当这个条件它成立了,那我就处理语句块,处理完语句块之后,再处理后面的部分。 那如果你这个判断条件不成立了,不成立怎么办呢?那我就直接跳过这个语句块,执行后面的部分。 接下来我们看一个小小的这个案例啊,首先通过 ev 语句, 这里面是一个关系表达式,括大一等于六十,那么括的值 啊,假设它是多少一百,那一百大一等于六十,结果是成立的,成立就是为真,为真的话,那么就会执行后面这一条语句 叫做什么? print for 等级冒号及格,就将这个双引号里面那个字符串进行输出,写杠音放行。 但是我们要注意单分式结构啊,只有在条件为真的时候啊,才执行给定的操作,如果条件为假,则它就不执行任何的操作。 这一点大家一定要明白,就是当这个条件成立的时候,他才会处理这个一句话,如果你不成立,他就不自信。那接下来我们看一下相关的啊,部分说明 条件啊,均为逻辑表达式或者是什么呢?关系表达式也可以是任意的数字型。什么意思?比如现在 x 的 值是几啊? 给它赋了一个初值为二啊,定为整数变量,直接判断 if 括号里面三, 直接打印的是 ok, 总有两个点啊,什么意思啊?只要这个条件,表达式里面不为假,就是为真。 第二个你看是什么字母?常量 q, 他 也是非零啊,所以他也会输出,输出什么?百分之低用来输出单引号 a, 哎,但是要注意了, 单引号 a 的 阿斯科马用十进四输出,那小写 a 的 阿斯科马什么?他输出的是九十七,这一点大家一定要搞明白啊。下面我们再一次判断这个表达式判断条件, 这中间是一个什么呢?是一个逻辑语,逻辑语的规则你要记着啊,要求左右两边为真,结果为真,其余全部为假。所以三小于 x, 三小于二,结果为假。 x 小 于等于五,那二小于五是成立的,结果为真,那一假一真,结果为假为假的话,他就不会执行后面这一条语句。 接下来我们来看第二点,语句可以是单语句,也可以是复合语句,注意在复合语句发括号外面不需要加分号。接下来我们看一个案例, a b, t 把它定为整形,这个边量再判断 a 大 于 b, 如果这个条件为真,它就会处理发过号里面的三条语句,如果为假,它就不执行。 现在我们来看一下,打开这个编辑工具,先建一个工程, 找到这个 windows 桌面向导 if 一 记 demo 回车 空项目单机确定,这个时候就创建成功了,直接在源文件夹里面创建一个啊, c 源的文件来写代码 d, m 点 c, 可以 了,井号 in cloud, s, t, d, r, o 点 h, 再写这一个什么呢?慢函数。 接着什么呢?我们首先看第一点,它这里一浮一记,后面是一个 条件判断这个表达式,那如果我写的是什么呢?我写的是这个八,然后后面直接来一个 print for, 写一个什么呢? ok, 换行这个到底它值不执行啊?我们执行一下,你看结果, 结果输出的是 ok, 那 为什么输出 ok 呢?你要记住这个表达式判断的条件,只要记住一点,只要这个判断啊,条件为非零的, 非零词,即表示为真,那八他就不是零,不是零的话,那么证明这个判断这个条件他是成立的,成立的话就执行后面这个语句, 这是第一种。那么第二种是什么呢?刚刚讲了,你看单引号里面什么,这个 q, 是 吧?这是字母常量是一样的,它也是非零,那么它输出什么呢?它双引号里面输出,你看啊, 它输出的是百分之低,看啊,它百分之低,换行逗号,那我写什么呢?它字母啊,大写啊,字母小写 a, 是 吧?好,我们再一次,你看我印写一下啊, 你就知道结果了。直行看到没有结果的话,这个小写 z 是 一百二十二,这个是没有错啊,因为 字母 z 小 写是九十七到一百二十二,那么 z 就是 一百二十二嘛,以实心式的阿斯特码输出。那如果我换为什么呢?换为 a, 小 写 a, 我 们再看一下结果 再执行,你看没有结果九十七,那跟什么?跟我们刚刚讲这个事,你看一模一样的,是吧?那后面我们看第二种啊, 复合语句怎么执行?现在我们来看一下这个工程案例到底是如何进行操作的。 比如下面我写个 if, 一 记这个四十五大于九, 它就是个关系啊,表达式满足这个条件,我就用花括号输出,看啊这条语句输出这个幺幺幺换行, 然后再来二二二三三三啊,二二二三三三,可以了,现在我们执行一下, 结果你看一下出来了吧,三个一,三个二,三个三。但是如果你这个条件不成立, 比如啊,这个条件不成立,我改为什么四十五小一九,那你不成立,不成立的话他发括号啊,整体里面每一条语句都不执行,他 看作是单条语句再次执行,你看什么都不执行啊,只输出 ok 和这个九十七,那后面不执行。现在我们回头过来看一下我们这个啊,课间 那么刚刚讲这些东西,大家一定要明白。接下来我们看一个案例,键盘输入一个整数,告诉我们了输出该数的绝对值, 那我们判断绝对值,那首先你要判断这个数到底是大一点还是小一点,那小一点的话,那就取还就可以了,是吧?那如果他是正数的话,那就绝对值就是本身。 那首先我将这个变量定为整形,然后请输入一个整数 百分百分号,百分号低冒号。那么两个百分号在这里只表示输出一个百分号,所以输出结果才出现什么呢?请输入一个整数百分之低冒号,看到没有? 接下来是看货从键盘接收输入的这个标准输入函数百分之低,以实心字进行输入,那这个变量数的这个变量前面加了个地址符号,现在他输的是什么?负九百五十六。 接下来再一次判断这个条件,判断了一副语气了,负九百五十六, 负九百五十六是什么?他小于零,小于零,那么证明这个判断条件的表达式是成立的。成立的话呢,那就执行下面这条语句,你看本身他是负九百五十 六,是吧?那么前面再还有个负了符号了,负啊,负,负得正对不对?最后竖的这个边上就得到正的 九百五十六,最后我们输出该竖的绝对值为冒号,你看照样显示 百分之一是专门用来输出数的这个变量数,这个变量是多少?九百五十六,那么他这地方就显示的是九百五十六。最后程序结束,这是一复一记的第一种形式啊, 接下来我们看第二种。第二种形式,首先他也是一样的一副语气,后面也是这个判断条件来表达式,那么这个判断条件 啊,成立,他就会执行发括号里面语句快一,如果你这条件啊,他不成立,为假为假的话,就执行 else 后面的语句快二,用发话括起来。执行过程。这里告诉了我们 判断条件成立,那么执行语句快一,否则执行语句快。现在我们看一下这个流程图啊, 你看,先判断条件,条件成立,我就处理语句快一,最后再结束。如果判断条件他不成立, 那么就执行语句快二,执行完之后程序就结束了。那下面举来个例子,大家来观察一下啊,什么意思? if 后面这个关系表达是括啊,如果括的值是六十五, 那么六十五大于等于六十,这个结果成立,成立的话,就输出等级为及格吗?等级冒号及格。那如果你括的值是多少?如果你括的值是五十二, 五十二大于六十没有,等于六十也没有。所以啊,他就处理 else 后面的这个什么 else 后面的这个等级冒号不及格, 这大家一定明白啊,如果成立,就执行语句快。一、他不成立,执行语句快。现在这里是什么?单条语句,只有一条语句可以不要加括号,如果你要执行多条语句,就用括号把它括起来,形成语句快, 注意一下 else 子键啊,是 if 的 一部分,这个是对应关系,不能作为语句单独使用,必须以 if 进行配对。 那现在我给你举个例子,我把这个啊先注视掉,快注视是吧,然后再往下面干什么呢?如果这个 三大于四,那么三大于四的话呢?我就输出这个什么呢?输出 ok, 换行, 否则否啊, else 我 输出 no n o 点反行。那现在我们执行一下,你看三大于四这个条件成没成立,那不成立嘛,不成立的话肯定输出 no, 那 如果它成立就输出, ok, 好, 我们执行一下, 结果输出的是 no。 那 现在如果把这个关系啊改一下,我改为小 e 三,小 e 四是成立的,成立的话就输出什么,就执行这个输出, ok, 你 看 再次运行,那 ok, 所以 ef 和 else 一定要配对好, 当这个判断条件的表达式成立,它就处理 if 和 else 中间的这个语句块,如果它不成立,就执行 else 后面的语句块。二。好,接下来我们来看一下 这个什么呢课程案例啊,这里啊,它要求什么呢?要求计算 y 的 值,这个数学的一个函数形式啊, 在什么样的情况下会执行三乘 x, 三 x 加六是吧?当 x 大 于等于零的时候,它就执行三 x 加六。 那么当 x 小 一点的时候,他会执行什么?执行这个负 x 的 平方加上二 x 减八啊,就是求 y 的 值嘛。 那么我们写程序怎么写的?因为你记上这些数据可能会带有小数点,所以我们在定变量的时候, x 和 y 这两个变量要定为什么否点型, 我写的是什么?当精度,你也可以写什么 double, 那 接下来就输出提醒用户请输入数据百分之 f 冒号,你看这就照样显示了,就出来阴性结果就出来这一条, 你看四 count four 百分之 f 是 从键盘数 x 的 值,这个数 x 的 值,我数什么数?五点六。 好注意啊,这个数 x 的 值得到五点六。那么接下来我们有一个 if 和 else 的 这个条件判断, 那 x 是 五点六,那你就把这个五点六写到这来了。五点六,那五点六大一等于零,这个条件是成立的,成立式为真为真,就会执行 e 符合 else 中间的这个部分,那么 y 就 等于三乘上 x 再加六。 那计算完之后呢?他最后就直接执行后面的输出, y 等于百分点二, f 放行,那百分号是以格式说明,符点二, f 就是 小数点,保留两位,你看输出的结果是 二十二点八零,保留两位小数,最后程序结束。这就是如何计算这个函数啊,对应的值。 接下来我们看本节课的第三种形式,易复以及啊,这是多个条件判断了,我们来注意一下 易复,后面是个表达式一,什么意思?当这个表达式一条件成立为真,就会处理语句块一, 如果你这个地方它不成立为假,再判断 if, 再判断那个表达是二。如果表达是二为真,就执行后面的语句快二,发过号啊。 如果你语句二不成立,它就再判断表达是三,依次类推,哪一个表达式成立,它就执行哪一个后面的语句快,如果所有的上面都不成立了,那就执行 else 后面的语句快 n, 那么中间其中有一个成立,执行完之后就跳出这个 if else 中间的这个输入的操作。那现在我们来看一下这个执行过程, 从上面到下面进行检测。表达式,当某一个表达式成立的时候,则执行它对应的这个什么语句块,执行完之后就跳出整个 if else 了, 执行其他的部分,就执行后面这个部分了,对不对?后面这部分代码,如果所有的表达式都不成立,那就执行什么呢?语句快 n, 就是 else 后面这一栏,这个大家一定要明白,那接下来我们看一下这个图形就明,更加的容易理解, 你看啊,首先你要判断表达式为真嘛,为真就执行语句快一,最后就结束了。 如果你围甲再判断第二个,围甲再判断第二个,如果第二个还是围甲,我们就判断第三个,如果第三个成立啊,我就处理这个语句快三,处理完之后,就跳出这个 f 啊, else 这个啊。条件判断,再执行后面的部分, 如果所有上面都不成立了,那肯定有执行,是吗?最后一个了,就是语句 n, 那 现在我们来看一下这个程序的相关操作,你看啊, 我们要计算什么?计算 y 的 值怎么计算的? x 大 于零,那么就 x 减七, x 等于零, y 等于二, x 小 于零,它就三 x 的 平方。 那首先我们初使画一个变量 x 嘛,你要给 x 确定值,然后判断 x 是 否大于零,如果它大于零,那我就执行 y 等于 x 减七,最后就结束了。如果你第一个不成立我,我再什么再判断第二个嘛, x 是 否小于零, 如果 x 小 于零,那就等于 y 等于什么?三乘上 x 再乘 x, x 的 平方嘛,就相当于两个 x 相乘。哎,如果你这个啊,执行完之后就结束嘛,如果你这个地方不成立,就执行 n 后面那个部分就直接 y 等于减, y 等于二了。 好,那现在我们看一下这个延代码啊,这个预处理命令我就不讲了,接下来再执行主函数,开始 x y, 请输入百分之这个 f 的 这个相关数据,你看,请输入数据百分之 f 冒号, 接下来我输一个什么 x 的 值,我输六,然后再判断 if 六六大于零成不成立,六大于零是成立的, 成立的话 y 就 等于什么六减七,六减七的话,它不够减,那么结果是负一负给 y, y 就 得到负一。执行完这个语句之后就跳出这个 if else 就 执行后面这个部分,就输出 啊,百分号点二 f, 那 保留两位小数,所以他输出的结果是负一点零零。 这就大家一定要掌握这些相关的细节操作。那接下来我们来看一下几个例子啊,那我要求大家做一个什么样的程序呢? 看一下啊。嗯,是这样的,要求 从键盘输入一个字母,判断这个字母 是否为这个字母,字母又分为大写或者是小写,你都要判断啊,第一个是字母还是数字, 我就判断这两种,其他我就不再判断。如果你还判断,你可以判断什么,可以判断个其他字母啊,什么之类的,是吧?好,接下来我们来看一下, 那么这里有个要求啊,为什么呢?你必须要注意的是一个点是什么呢?如果你判断的是这个八写字母,你也可以用这个字母啊,八写 a 或者到什么 半写 z 的 这个方法进行判断。这是第一种形式啊,判断这个条件你也可以采用这种形式,小写 a 啊,对,好,小写, 看着啊,小写 a 到小写 z, 数字就是什么数字的话,就是看啊,数字 啊,就是零到什么,这个零到 九这种方式就可以判断出来。 ok, 好, 接下来我们来观察一下啊,观察一下,这是一种形式,要不你不是这种形式也可以,你可以把这个改。为什么呀?大写 a 是 六十五到九十这种也可以啊,阿斯科马判断也可以,这个是九十七到一百二十二, 那如果是零到九,你可以是四十八到五十七,这是判断条件的一个范围,大家一定要明白,这是对应了 a, s, c, i, i 就是 阿斯科马,阿斯科马这个判断方法啊, 阿斯科码字母对应的阿斯科码。好,那现在我们就写代码,写代码,首先呢,我就定一个啊,定这个 try 字母变量啊,这个啊, c, h 了,定完之后,那这个字母变量是从键盘输入的, 那我提醒用户, print 的 值冒号, 你也可以啊,不放行也可以啊。然后呢?接下来从键盘输入 c, h 就 等于什么? get, 我 们以前讲过了, get try, 从键盘接受一个字母,放到 c、 h 里面去 这一条语句。第三十二,这个条语句啊,就是从键盘输入一个字母,是吧?到 ch 里面来,那接下来你就判断那个 ch 就 可以了,是吧?如果啊,如果什么 先判断那个小写字母,那就如果这个 ch 啊,它大于什么呀?大于或者是等于这个什么 大写 a, 先把它大写啊,同时它又满足什么呢? c, h, 小 e 等于多少啊?这个大写 z, 那 我就输出是大写字母 print four, 你 看就出来了,大写 大写字母,然后再往后面判断 ls, 如果你不是大写字母 s, f, 再次判断你就是什么。我也判断小写字母啊,这个小写 a 到小写 z 啊,这个就是小写字母,再往后面判断是吧? s, f, 再判断啊,这个是零到什么到九,那这个是数字, 这就可以判断出来了啊,这个就是数字。好 else, 否则 else 啊,就输出,告诉用户其他字母放行。 接下来我们做一个调试一下啊,看结果,比如现在输一个字母,现在我输大写 k、 f, t, 你 看大写字母没错吧? 我们再看一下啊,再执行一下,如果 c、 h 的 字,我输小写小写 x。 肥车,你看小写字母, 再一次执行,如果输数字这个八,你看肥车, 他显示了什么数字,为什么?因为你第一个条件不成立,他就会判断第二个,第二个小小写字母又不成立,那第三个呢?你看这个八正好在零和九之间,所以他输出的是数字,那如果你输其他字母, 比如我输这个警号飞车,你看其他字母,他就提醒你。 所以啊,这就是 if else if else if 就是 多种判断条件,就用这种格式,所以大家在学习的时候千万不要着急,慢慢去思考。那同时我们可以换一下,我不用这个大写,可以用什么?可以用六十五到 九十,那我们再看一下对不对啊?也可以用阿斯科马去判断直行。 比如现在我输这个小写 f 回车, 我们输的是提示小写字母,这就是我们可以通过字母常量的本身,也可以通过阿斯科码形式进行判断,你从键盘输的这个字母到底是大写还是小写还是数字。 那这节课这个内容我就给大家讲到这里,如果在学习过程中有哪些不理解不知道的, 可以通过 qq 跟我在线进行进步的沟通与交流。本节课就讲到这里,下一次课再见。

你是否也曾盯着满屏的翻译报错陷入迷茫,想靠 c 加加进阶高新赛道,就被指真模板和内存管理折磨的怀疑人生?不是你不够努力,是你缺少一本能真正带你打通 c 加加底层思维的硬核工具书。 由 c 加加语言之父比亚内斯特劳斯特卢普亲自主导的 c 加加程序设计语言第四版二零二六年重译版正式出版, 被全球开发者奉为 c 家家领域的官方说明书。这道书凭什么被称为殿堂级经典?第一,它讲的不是死记硬背的 a p i 调用,而是 c 家家的设计思想和语言体系,让你真正理解每一个语法特性背后的底层逻辑。第二,全书分为基础认知、基本特性、抽象机制和标准库四大篇章。 从 c 加加的发展历程到 c 加加十一星特性全覆盖,既是入门指南,也是进阶手册,一本顶三本。第三,书中每个知识点都配有大量 c 加加十一标准代码视力,让你在实战中真正吃透面向对象和泛型编程的精髓。 c 加加从来不是过时的语言,在游戏引擎、自动驾驶、量化交易、大模型推理框架这些对性能要求极高的领域, c 加加依然是绕不过去的主力工具。 高级 c 加加工程师的年薪普遍在四十万到两百万之间,真正的高壁类、高回报,与其在海量业务系统里卷生卷死,不如静下心来啃透这本殿堂级经典,用底层硬实力拉开真正的差距。

你写的代码, ai 也能写,那你的核心竞争力在哪里?当你只会调 api 抄代码,未来的大厂为什么还要招你?答案很简单,当 ai 让答案唾手可得时,思考反而成了稀缺品。而今天,这本书就是教你真正思考的语言,它就是 c 加加之父比亚内斯特劳斯特鲁普亲手写的 c 加加程序设计语言第四版, 二零二六年全新一本江湖,代号 t c p l。 这本书有多重?全球销量千万册,被翻译成近二十种语言,在亚马逊最佳编程书籍榜上稳居前列。 全世界想真正学好 c 加加的人,书架上都绕不开它。它不是教你一行行敲代码,而是教你怎么设计系统,怎么管理资源,怎么写出能用四十年的程序。第四版,基于 c 加加十一标准全面重写,从内置类型讲到面向对象,从范型编程讲到标准库,每一章末尾都有作者四十多年经验的建议。 有读者说,这不是一本编程书,而是一本 c 加加百科全书。你可能会问, ai 框架的底层核心全是 c 加加写的, 自动驾驶的感知系统、高频交易的撮合引擎也全是 c 加加。因为在性能和稳定性面前, c 加加不可替代。这本书就是你进入高阶开发的通行证。新版二零二六一本,由人民邮电出版出品,一文流畅,编排清晰。 如果你是一个想练内功的程序员,一个想跳出内卷的开发者,这本书会让你明白什么叫真正的编程思维,带你读好书,看透技术!

今天我们要聊的呢是 c 家家里面的文件流,就是如何用文件流去进行文件的读写操作,包括如何去管理文件的生命周期, 还有就是文件模式的一些细节。咱们先来说说,就是文件流的概述,就是在 c 家家里面要实现文件的输入输出,主要会用到哪些头文件和哪些核心的类。嗯, 在 c 加加里面,你要做文件的 i o 操作,就必须要包含 fstream 这个头文件,然后它里面有三个非常重要的类, 一个是 ifstream, 它专门用来读文件,然后 offstream 是 专门用来写文件的。还有一个 fstream, 它是可以同时读写文件的,使用起来也很方便,因为它们都继承自 i ostream 类型,所以可直接附用我们熟悉的输出计算符和输入计算符。 明白了,那文件流操作的关键思想是什么?其实核心就是你先创建一个文件流的对象,然后把它跟一个实际的文件做一个关联, 之后你对这个流的操作就会直接反映到文件上面,而且是高效的。我还有一个疑问啊,就是这个 fstream 它有哪些自己特有的成员函数可以对文件进行操作呢?比如说你可以用默认的构造函数创建一个文件流对象,然后用 open 成员函数去把它和一个文件进行绑定。 或者说你可以在创建对象的时候,就直接通过构造函数指定要打开的文件名和打开模式,那对应的成员函数就是 close, 它可以帮你关闭文件,你还可以通过 is open 这个成员函数来查询当前这个文件是不是已经成功打开,并且还没有被关闭?了解了,那下面我们要说的就是这个创建和打开文件的不同的方法, 就是我们在代码里面到底怎么去打开一个文件,怎么去把这个文件流对象和实际的文件关联起来。打开文件其实有两种常见的方式,一种就是你在定义这个文件流对象的时候,直接在构造函数里面把文件名传进去。 比如说我们的代码市历里使用字母串字面值 ifil 作为参数,定义了一个 ifstream 类型的对象 in, 这样就定义了一个输入文件流 in, 并且同时打开了 ifil 这个文件。还有其他的打开方式吗?当然有,还有一种方式是你先定义一个文件流对象, 然后后面你再用这个 open 函数去打开文件。而且 ifstream 和 ofstream 用法上也保持一致。例如我们可以先用 ofstream 的 默认构造函数创建一个名为 out 的 函数,然后再通过对象调用成员函数 open 关联具体的文件。 哦,我还有一个疑问啊,就是这个文件流对象在它的生命周期里面能不能够反复地去打开和关闭不同的文件?可以啊,你可以打开一个文件,然后做一些操作,然后用 close 把它关掉,之后再用 open 去打开另外一个文件, 就可以很灵活的去切换。好的,我们继续往下说,就是这个检查文件打开状态的重要性,就是为什么我们在对文件进行读写之前,一定要去检查这个文件留对象的状态呢?其实原因很简单,因为你打开文件这个操作它有可能会失败。嗯,比如说这个文件根本就不存在, 或者说这个文件的路径你写错了,或者说你当前的程序没有权限去访问这个文件,那这些情况都会导致你打开文件失败。 如果你不检查直接去读写的话,你的程序就可能会崩溃,或者出现一些莫名其妙的问题。哦,那我们一般是怎么去检查这个文件流对象它是不是处于一个有效的状态呢?最常用的办法就是直接把这个文件流对象放到一个 if 语句里面去判断它是不是为真。 如果这个文件打开成功了,那它就是一个处的状态,就可以继续执行下面的读写操作了。听起来很方便啊。对,其实它背后是这样的,如果文件打开失败了,它会自动地把这个流对象的 fail bit 这个状态位给置位, 然后你去判断的时候,就相当于在检查这个状态位。我明白了,我们再来讲讲这个读写销售记录的函数设计, 就是我们要怎么去设计这个 read 和 print 函数,让它们可以不局限于标准输入输出,还可以灵活地适配文件或者其他的流。我们可以把 read 函数设计成,它接受一个 stream 的 引用和一个 sales data 的 引用,然后它从这个 stream 里面去读取 isbn 销量和单价, 然后计算一下销售额,最后把这个 isstream 再返回出来。 print 函数也是类似的,它是接受一个 ostream 的 引用和一个常量的 sales data 的 引用,然后把这些数据格式化的输出到这个 ostream 里面, 这样的话,其实我们这两个函数就不关心数据是从哪里来的,要到哪里去。也就是说这两个函数都具有一定的通用性,能够支持控制台的输入输出,也能够支持文件的输入输出。 那你可以再讲一讲这个 read 和 print 函数在实际操作文件时具体是怎么用的吗?当然可以,比如说我们有一个输入的文件名和一个输出的文件名,那我们就可以先创建一个 ifstream 和一个 offstream, 然后把这两个文件名分别传进去, 这样就打开了这两个文件。接着我们就可以定义一个 total 的 sales 下划线 data 来存这个总的销售记录,然后用 read 函数从这个输入文件里面去读,每读进来一条记录,我们就去判断一下它的 isbn 和当前的 total 的 isbn 是 不是一样的, 如果是一样的,我们就把它合并到 total 里面,如果不一样的话,我们就把 total 打印到这个输出文件里面,然后把当前的这条记录设置为新的 total, 这样一直循环下去, 最后我们把最后一条 toto 再打印出来就可以了。好的,那我们现在要讲的就是这个自动管理文件的生命周期,那这个是怎么通过对象的作用域来实现的?以及这样做到底有什么好处?其实就是当一个标准输入输出流的对象,例如我们代码是例里的 ifstream 对 象 input, 它离开了它的作用域,比如说它所在的这个函数执行完毕了,或者是说你用花括号限定了一个块儿,它离开了这个块儿, 那么它的 c 勾函数就会被自动调用,然后 c 勾函数里面会自动地去调用 close 方法,所以就不需要你手动地去调用 close 了, 这样的话就会让你的代码很简洁。而且最重要的是它可以帮你避免因为忘记关闭文件而导致的资源泄露,就算中间发生了异常,这个对象也会被正常地销毁,然后文件也会被正常地关闭。嗯, 那你可以举一个例子说明一下,这个 f s t r e a m 对 象是怎么自动被销毁并且自动关闭文件的吗?比如说我们有一个函数,它是处理命令行参数里面的一系列文件,那我们就可以在一个 for 循环里面,每次都创建一个新的 ifstream 对 象, 然后用这个文件名去促使化它,那这个文件就打开了,接着我们就可以对这个文件进行一些操作,如果打开失败了,我们可以输出一个错误信息, 每一次循环结束的时候,这个 ifstream 对 象就会自动地被销毁,所以它所对应的文件也就会自动地被关闭,我们就不需要去手动地调用 close 方法了解了。那接下来我们要聊的就是这个文件模式,对吧?那你先跟我们讲一讲都有哪些文件模式,然后它们分别是用来干嘛的? 好的,在 c 加里面,每一个文件留对象都关联了一种文件模式,这个其实就决定了我们可以对这个文件做哪些操作。那最常用的比如说 in 就是 止读模式,然后 out 是 止写模式,如果文件不存在的话,就会新建一个 app, 是 每次写之前都会跳到文件末尾,相当于追加,然后还有 trunk, 会把之前的文件内容清空。 eight 是 打开文件之后会把文件指向移到末尾,但是你后续还是可以在任意位置写的。最后还有一个 binary, 就是 以二进置的方式来进行读写,这个一般是用来处理非文本文件的。 ok, 我 想问一下啊,就是如果我们用 opstream 去打开一个文件的时候,如果我们不特别指定这个模式, 会发生什么意想不到的事情吗?如果我们不指定的话,它默认是 out 和 trunk, 也就是说这个文件一打开,它里面原来的内容就被清空了。 对,那如果你想保留原来的内容,然后只是想在文件末尾追加的话,你就必须要显示的指定 app 模式。好的,我们继续往下聊。就是这个文件模式的动态改变, 那这个文件流对象在使用的过程当中,能不能够随时地去切换打开的模式?比如说我一开始是想写一个新文件, 然后面我又想改成追加的方式,这个要怎么实现?其实这个文件流对象它的打开模式并不是说创建的时候就固定死的, 我们完全可以在关闭当前文件之后,再用同一个对象去打开另外一个文件,并且指定一个完全不同的模式。也就是说我们不需要每次都创建一个新的文件流对象,就可以反复地去打开不同的文件,用不同的模式。对,没错。比如说我们先创建一个 ofstream, 然后我们用它去打开一个文件,这个时候它默认是输出并且截断的模式,然后我们操作完了之后把它 close 掉,接下来我们再用同一个对象去 open 另外一个文件,并 且我们可以指定 app 模式,那这个时候就是追加了,所以这种方式就非常的灵活,你可以根据你的需要随时地去切换读写的方式。 ok, 我 们今天把这个 c 加的文件流从头到尾过滤一遍, 包括怎么打开文件,怎么读写文件,怎么去管理文件的生命周期,以及各种文件模式的细节。最后还有一些常见的容易踩的坑,希望大家听完之后对文件操作能够有一个更清晰更全面的认识。好了,那今天的内容就到这里了,然后我们下次再见吧,拜拜。拜拜。

为什么 c 加加里不管读键盘、读文件还是读字符串, i o 代码都长得一模一样?今天这一章节深入介绍 i o 类, 咱们第一个要聊的是这个 i o 操作的基本的概念。那我想问一下,就是 c 加加里面是怎么做到用一套代码就能处理不同的设备和不同的字符大小的? 其实在 c 加加里面,不管你是要从键盘读入还是要读一个文件,或者是说要通过网络传输数据,它的这个输入输出的操作的逻辑都是一样的。 嗯嗯,它不会说因为你这个设备不一样,你就要写不同的代码,这么说的话,写代码的时候就不用关心 具体是哪个硬件了。没错没错,就是 c 家家的标准库。通过这一系列的类,比如说 iosstream, 把这些底层的差异全都屏蔽掉了。对,然后你不管是要操作文件还是要操作控制台,你都是用这一套接口去读写数据就可以了。我们来认识一下 i o 流大家族,先有个大概印象, 关于什么是继承我们之后的课程会有详细的介绍。整个 i o 类分为两大主干,输入流和输出流。输入流的基类是 i stream, 输出流的基类是 o stream, 两者共同派生出了 i o stream, 也就是我们最熟悉的标准输入输出流。 在此基础上又延伸出了两类专门的流文件流,包括 ifstream 读文件, offstream 写文件以及同时读写的 ofstream。 字串流,包括 e string string 读字串、 o string string 写字串,以及同时读写的 string string。 简单说就是以输入和输出为根,长出了控制台、文件和字串这三大分支,它们共享一套操作方式。好的,我们已经了解了 i o 操作的基本概念,接下来我们要探讨的是 c 加加 i o 库的核心头文件和类。我想问一下,就是这些头文件 分别都负责哪些功能? c 加加的 i o 库,它的核心就是有三大个头文件嘛。第一个是 i o stream, 主要就是负责标准的输入输出,嗯,然后 f stream 就是 负责文件的操作。还有一个是 s stream, 就是 做字母串流的操作。那这三大类下面 又分别都有哪些具体的类去对应不同的操作和字体类型呢?呃,从大的类型上面分呢,就是有输入流、输出流,还有就是双向流。嗯,那每一个又有窄字符和宽字符版本。嗯,就是为什么这些 i o 对 象 不允许被拷贝或者赋值呢?因为这些 i o 对 象,比如 extreme o stream 这些对象,它们在被拷贝或者赋值的过程当中会出现一些状态的混乱。嗯, 你在读写的过程当中,这个状态是会变化的,所以 c 加加直接就不允许你去拷贝或者直接赋值,它只允许你通过引用来传递,而且这个引用还不能带 const。 懂了懂了。然后我们再来说一下这个管理流的条件状态,就是 a o 类里面,它是怎么去定义这些标志和类型来表示这个流当前的状态的。 i o 类里面,它是定义了一个叫做 i o state 的 类型,这个其实就是一个机器相关的整数类型,它是被当作一个未集合来使用的。 嗯,然后它里面有一些常量,代表了一些特定的位,比如说 badbit, 就是 表示系统级的严重错误,流已经崩溃了。 failbit 表示 i o 操作的逻辑失败。比如你要读一个数字,但是你读到的是一个字母, e, o, v b, t, 表示已经读到了文件末尾。还有一个 goodbit, 它的值是零,表示流没有任何错误。那这些成员函数,像 eof, fail, bad 个的这些乘以函数是怎么跟这些状态标志去对应的呢?这些函数就是用来查询流的状态的,比如说 eof, 就是 去检查 e o bit 是 不是被置位了。 fail 是 去检查 fail bit 或者 bad bit 有 没有被置位,然后 bad 就是 专门检查 badbit。 good 是 只有当所有的错误位都没有被置位的时候,才会返回出。嗯嗯,只有当 good 返回出的时候,这个流才是完全没有错误的,你才可以放心地去进行读写操作。原来是这样啊,那我们可以通过哪些成员函数去手动地修改流的状态呢?可以用 clear, 这个函数是把所有的状态位都清 空,然后流就会变成有效状态。还有一个 set state flex, 这个是可以根据你传入的这个标志位置位。 嗯嗯,就是用来主动地去设置一些错误状态。我有个疑问啊, clear 是 不是也可以只清空一部分标志位呢?对, 其实 clear 它是有一个带参数的版本,就是 clear flex, 它是可以根据你传入的这个标志位去有选择性的复位。 哦。然后还有一个函数叫 outer state, 它是可以让你去读取当前流的完整状态,它会返回一个 io state 类型的值,你可以用这个值去做一些判断或者保存起来。了解了能不能举一个实际的例子,就是这些状态管理的函数是怎么配合使用的。 我们看两段核心代码,示意第一段,保存并恢复流状态代码是这样的,首先我们用 auto o state 等于 scene 点 r d state, 把 scene 当前的状态保存下来,然后调用 scene 点 clear, 让 scene 恢复到有效状态。 接着我们调用 processing put 函数,使用 scene 完成我们的操作。最后再用 scene 点 set state, 把 sin 恢复到原来的状态。这样做的好处是我们临时修复了流状态,但不会影响它后续的行为。第二段,精准复位指定状态位代码是 sin 点 clear, 参数是 sin 点 r d state 与运算非 sin 点 fill bit, 再与运算非 sin 点 bad bit。 这行代码的作用是指复位 failbit 和 babbit 这两个错误标志位,而保留其他标志位不变,比如文件结束位,它通过未运算实现了更精细的状态控制。 哎,我还有个问题啊,就是这个输出缓冲区,它到底是怎么实现提升程序效率的?其实每一个输出流,比如说 cot, 它都会有一个自己的缓冲区,那这个操作系统呢?就会把你的这些多次的输出操作都暂时的存放在这个缓冲区里面, 然后等到一定的时机,再一次性的把它们都写到这个目标设备上面,比如写到磁盘或者写到显示器上面。嗯, 因为这个实际的写操作是比较慢的,所以这样合并之后就会减少这个写的次数,程序的运行效率就会提高很多。那我们在写代码的时候怎么去控制这个缓冲区的刷新呢?就让它立刻把内容输出出来, 可以用一些操作符来强制地刷新这个缓冲区。比如说你用 endlef, 它是输出一个换行,然后再刷新。 flush 就是 直接刷新,不输出任何东西。还有一个 ends, 它是输出一个空字符,然后再刷新。 ok, 你 还可以用 unibuff 这个操作符,你一旦设置了之后呢,之后的每次输出都会自动地刷新缓冲区,直到你用 nonibuff 把它关掉为止。 哦,我还想知道这个流的关联到底是个什么东西?就是这个输入流和输出流关联之后会有什么效果?流的关联,就是说你可以让一个输入流,比如说 sin 和一个输出流,比如说 cut 关联起来, 那这样的话,每次你从 sin 去读数据之前,它都会自动地先把 cut 的 缓冲区刷新 哦,这样的话你就可以保证,比如说你给用户的提示信息一定会在用户输入之前显示出来。如果我想要去改变这个输入流的关联, 或者说我想要暂时的取消这个关联,应该怎么做呢?你可以用这个 time 函数,比如说星 time, 然后参数写取地址运算符。 cot 就是 把 sin 和 cot 关联起来,其实 sin 默认就是和 cot 关联的,你也可以传入一个空指针来取消关联哦,那这个 time 函数它是会返回你之前的那个关联的流的指针,所以你如果想要恢复原来的关联的话,你可以先保存一下原来的指针。 ok, 今天咱们把这个 c 家里面 i o 流的一些基本原理状态的管理,还有缓冲区的机制都聊得明明白白。嗯,对,相信大家以后在处理输入输出的时候应该会更有底气了。行,那今天就到这里了,拜拜。拜拜。

大家好,欢迎来到博兴教育,我是天狼。第三讲思域关键字,本节课带着大家来学习思域的相关关键字。关键字又称为保留字, 就是已经被 c 语言本身使用的,由系统和编辑器指定的保留字,不能做其他用途使用的。那接下来我们来看第一类 存储类型关键字, auto 自动存储 static 静态存储, register 集成器存储 exten 声明,一个外部的全集变量。接着我们来看第二类数据类型关键字。 第一个是字母型、双精度、 美举类型、单精度整形、长整形、短整形。有符号类型、 结构体类型、联合体类型、无符号类型、空类型。其中后面带有一 bet 八 bet 四 bet。 这里是告诉我们这个关键字数据类型在计算机当中所占的字节个数。 接下来我们看第三类控制语句关键字或 do well, 这些都称为循环语句 break, 它是什么?跳出当前循环, continue 结束当前循环,开始下一轮循环。 if 条件语句 else, 它是否定分支,以 if 进行配合使用。 go to 无条件跳转语句, switch 开关语句, case 开关语句的分枝 default。 那 接下来我们看第四类, 第四类呢?首先我们看第一个是专门用来声明只读变量的,那第二个呢?它是计算数据类型啊,在计算机账记的 字节长度。第三个是用于给这个数据类型取一个别名。 第四个说明变量在程序执行中可以被隐含的改变。第五个就是子程序,它的返回语句 共计分为室内。同时啊,除了三十二个关键字以外,后面就是 一九九九年十二月十六日, iso 推出了 c 九九标准,同时也增加了五个关键字。 接下来我们看第一个专门用来处理什么内联函数,那第二个的话呢?它是用来什么?只用于限定这个子真, 这个关键字用于告知这个编辑,为什么呢?就是所有修改该子帧所指向内容的操作啊,全部都是基于该子帧的 g, 它不存在其他进行修改操作的途径。那这样的后果是帮助这个编辑器进行更好的代码优化,生成更有效率的废编代码。 如果大家不明白也没关系,在后面的章节当中,我们会对所有的关键字一个一个的进行详细讲解。 那第三个是什么呢?是不玩内心,就表示这个真和假,那零表示假,非零表示真。第四个是负数, 专门来表示复数的,那复数类型包括一个实部和一个西部。那第五个这个关键字是表示这个虚数,虚数,虚数类型,它没有实部, 只有西部。那后面到二零一一年十二月八日, r s o 发布 c 研新的标准,叫做 c 幺幺标准,同时也增加了七个关键字。 那首先我们来看第一个关键字是专门用来干什么?对齐说明符,那后面这个是操作者了,那第三个是什么呢?原子类型说明符和这个限定符。 那第四个是干什么呢?我们可以利用这个关键字,可以简单的将一组具有不同类型,但是他有相同功能的函数抽象为统一的接口,就用这关键字来完成。 那第五个,第五个是什么?是表明我们调用啊,完成后的函数,他不返回主调函数, 还一个就是第六个断言啊,就是静态断言声明,第七个就是现层层土类型。 那本节课这些相关的关键字我就给大家介绍到这里,如果大家还有哪些不明白或者不理解,可以通过 qq 在 线进行跟我沟通与交流。 那各位同学,本堂课内容到此结束,下一次课再见!

图书宝宝们,大家晚上好,昨天呢我们讲解了一个非常重要的排序的算法,叫做冒泡法排序, 它在我们专升本当中相当于一个比较难的一个算法程序设计了,但是它的频率也是挺高的。今天呢,我们来讲一个非常重要的查找,叫做二分法查找,那使用二分法查找的时候呢,我们注意我们首先要进行排序, 那二分法查找呢?我们是放在数组当中进行查找的,所以呢我们第二步呢,要标上标,你比如说有 n 个元素,它的上标呢是零到 n 减一这样个位置。第三个呢,有三个指征需要我们以呃进行 移动以及后面的查找。要进行移动呃,我们用漏这个指征呢,指向最高的上标 n 减一, 那 me 的 这个指标呢?等于 lo 加上 high 除以二向下取整,那在我们这个呢,就二分之零加上 n 减一,应该是二分之 n 减一 的最低的这样的一个下标,那比如说 me 的 指向这个中间的这个位置,那开始去查找的时候,比如说给你一个值,我用 k 来表示进行查找的时候, 当 k 大 于密的时候,那我们是不是需要在右半边进行查找? k 大 于密的时候,我们去移动时针漏漏呢?等于密的加上一, 然后我们再去算密的,此时的密的呢等于漏加上害除以二向下取整,因为在这个时候呢,我漏我害这个时针,这个下标是不进行 修改的,我修改的是漏这个指征,因为他在右边这个区域进行查找了,所以漏这个指征呢,等于 mid 加一,然后再去算新的 mid, 那 k 小 于 mid 的 时候呢? k 小 于密的,我们是不是往左边进行查找?往左边进行查找的时候,我们 k 这个指数就变了, k 这个指数呢?等于密的减去一,密的减去一,我们再去算新的,密的等于漏,加上 k 除以二,向下取整。 那大家一定要注意,当 k 大 于密的时候,我移动的是漏这个时针,当 k 小 于密的时候,移动的是 k 这个时针, 那 k 大 于 mid 的 时候, high 这个指数是不变,是不移动的,然后 k 小 于 mid 的 指指小于 mid 的 时候,呃,我们的 low 这个指数是不移动的,大家要知道这个规律,那 k 等于 mid 呢?它是不是就是找到了, 找到了这样一个元素?那我们来看一下,我给大家一组数,比如说一三五 八七这样一组数字,它怎么进行查找呢?第一步我们先去进行排序,一三五 七、八,然后第二步,我们去标上标零一二三、四,你比如说我去查找五这个元素,给你的关键元素是五这个元素,我去标零漏这个下标,漏指的上标是零,那 high 指的上标是四, 那此时的密的是不是漏加上 high 除以二,那零加上四除以二等于二,然后指向的是二这个元素, 二这个商标指向的元素,那二指向这商标这个元素, k 呢?正好等于密的,我们找到了一次就找到了。你比如说我再去查找三这个数字,我去查找三这个数字的时候,此时呢 k 等于三,那我怎么办呢? k 等于三的时候, mid 现在是五, k 小 于 mid 了,我只移动的是哪个指针?我应该移动的是 high 这个指针, high, 这个指针等于多少? high 等于 mid 减一,那 high 呢? 等于 mid 减一, high 等于 mid 减一呢?应该是一这个元素,那 low, 那 low 呢?依然是等于零这个上标,那 mid 呢?等于 零,加上一除以二,零加一除以二,等多少?应该等于二分之零点五,零点五呢?它向下取整,应该是零这个元素, 然后 mid 也指向这个,那 mid 指向零这个元素了,那 k 呢?它是等于三。 mid 指向零这个元素,那应该是 k 大 于 mid 的 情况,因为此时的 mid 是 指向的是 一,然后 k 是 k 是 三, k 大 于密的情况。我移动的是漏这个时针漏呢,就等于漏加上一,那原来的漏是零,然后再加上一,应该是一这个元素,那漏也变了,漏指向的是这个元素, 漏指向元素,但是 he 这个位置是不变的。然后 me 的 呢?等于应该是一加上一除以二了,因为它上标是一了。一加一除以二等于一,那一这个下标位置呢?正好等于三,找到了两次就找到了,但是我们移动了两次时针,第一次呢,移动的是 he 这个时针,大家稍微的消化一下这个,这个,这一步呢, 找三个元素呢,相对来说稍微是比较难的。那我再重复一遍,我们使用二分法进行排序的时候,先进行 二分法,进行查找的时候,先进行排序,拿到一组数,我们先从从小到大排序,然后呢标去标,上标,标从零开始标上标,按照数组的标法。第三步呢,我们去找漏和亥,漏呢,是 指向零这个上标。 high 呢?指向是 n 减一这个上标,然后我们去分情况, high 大 于 mid 的 时候呢,我们往右边去查找,此时移动的时针,应该是 low 这个时针, 然后看小于密的的时候呢,我们用往右边去查找,此时移动的时针呢是 h 这个时针,然后 k 等于密的呢,就找到了,大家再去消化找三这个过程,找三这个过程呢,密的应该是,它指的是 五这个元素,他是 k 小 于密的。往左边去查找,我们动的是害这个元素,然后呢,他动了害之后找到的密的元素是零这个上标,然后 k 呢又大于密的元素了, k 大 于密的元素,我们此时移动的是漏这个时针,漏和害都指向了以一这个上标指向元素,我们 这个上标指向元素。一加一除以二等于一,向下取整等于一,我们就找到这个三这个元素,大家好好的消化一下啊。那我们今天的分享就到这里,关注我不迷路。

你为什么总是搞不定纸质和内存?为什么能用 c 加加写出能跑的程序,却总感觉自己在代码世界的外围打转?这不是你的错,你缺的不是语法,是内功。而这种内功,唯有 c 加加之复比阿内斯特劳斯特卢普亲自传给你,才足够正宗。 今天,我们读这本刚刚重译出版的 c 家家程序,涉及语言第四版。它不仅是经典,更是 c 家家四十年辉煌的见证者。这本书在技术圈被称为 t c p r 四,是真正的官方说明书。书中的每一行文字都是 c 家家语言设计者亲手摹写, 每一个建议都凝结了他数十年的实践智慧。很多人对 c 家家的印象还停留在复杂的指征和令人头疼的内存管理上,但现代 c 家家早已脱胎换骨, c 家家十一标准的发布,被作者本人称为一门新语言。这本书全面覆盖了 c 家家十一,并系统性的融入了移动语义、智能指征、并发编程等核心新特性, 让你告别你有 delete 的 噩梦,真正拥抱安全高效的现代 c 家家。为什么你迟早得读它?因为打基础你绕不开。 这本书讲的不是 api, 是 思想和体系,是从入门到高阶的完整知识链条。因为查漏补缺,它是最权威的答案。遇到模棱两可的问题,别猜了,直接翻它。更因为它一本顶三本,既是入门指南,也是进阶手册,更是程序员案头必备的 c 加加圣经。 想想看,操作系统内核、游戏引擎、高频交易系统、 ai 底层框架这些真正决定技术高度的领域核心代码,全都用 c 加加在劝退你,其实大厂核心岗位正在高星等着真正懂 c 加加的人。 这次二零二六年全新一本内容精进桩真升级,是你真正掌握系统级开发能力,跻身核心工程师行列的最佳时机。带你读好书,用底层代码构建顶层人生。

各位同学大家好,欢迎来到薄心教育,我是天狼。第一讲计算机程序和计算机语言,本节课从两大模块进行学习。 一、什么是计算机程序?计算机程序是一组计算机能够识别和执行的计算机指令, 主要运行于电子计算机上面,满足人们某一些领域的需求,信息化工具。 那在这个地方大家一定要掌握一个概念,计算机指令。 计算机指令就是指挥机器工作的指示和命令,程序就是一系列按照一定顺序排列好的指令。执行程序的过程就是计算机的工作过程。 控制器是专门靠这些指令指挥机器工作的,我们用这些指令来表达自己的意图,并且交给控制器去执行, 那只要让计算机执行这个程序,计算机就会自动的有条不稳的进行工作, 计算机所有一切操作都是由程序控制的,离开了程序,计算机将一事无成。 等到我们学完了 c 研之后,我会带着大家用 c 研开发出一些加密和解密等等相关软件。 那接下来我们要学习第二点,什么是计算机语言?计算机语言 是指什么呢?人与计算机之间的一个通信语言,也称为传递信息的路径, 就是人和计算机交流信息的,计算机和人都能够识别的语言,就称为计算机语言。 那计算机语言有什么?有 c 语言啊,有 c 加加,有帕斯克语言啊,有 vb 啊,有 java 语言啊,有 python 语言啊等等。 那从计算机的语言发展的角度来看,我们分为三个阶段,第一阶段就是机器语言,机器语言是由零和一组成的指令, 那机器语言它有什么优点呢?占用内存非常少,非常灵活, 直接可以执行,执行速度快,这是他的优点。缺点是什么呢? 可读性差,难以辨别和记忆,容易出错,因为他全部是零幺,零幺,可移植性也比较差。 那第二阶段废品语言。废品语言用一些简洁的英文字母符号串来替代一个特定指令的二进一出串。 那比如啊,在肺编研当中有一个指令 move m o v, 这个指令是数据传送指令,也就是啊,最基本的编程指令, 主要用于什么呢?将一个数据啊,从原地址传送到目的地址,那么它有什么特点呢? 这个指令就是不破坏原地址单页的内容。那现在我写一个啊,目 a x, 逗号两千 h。 这一条肺病炎的指令是用来干什么的? 那只要学会肺病炎都知道,但是没有学过,也不要着急,后面章节我会教给大家, 它是将什么呢?将一十六位数据两千 h 传送到 ax 这个继承器,那这就是一条肺病原所写的代码。那第三阶段是高级语言。 高级语言呢,是接近于人类的自然语言和一些数学语言。那高级语言有哪些优点呢?第一,容易学习和使用, 可读性非常好,便于程序员之间的沟通与交流,接近自然语言, 可移植性非常强。缺点是什么呢?高级颜需要经过变异连接后才可以执行,所以他的执行时间要慢一些。 这就是大家要掌握今后要学习的高级研,比如学完 c 研之后,我们会学什么?会写 c 加加等等。 那本节课主要是从两大模块进行教给大家。第一,什么是计算机语言, 大家在学习的过程当中有不懂或者不理解的可以通过 qq 来联系我,我们进行沟通与交流,告诉大家怎么去学好 c 语言。 各位同学,那本堂课内容就到此结束,下一节课再见。

c 加加函数到底是什么?行餐、食餐、静态变量、分离、变异这些概念你是否清楚?这节课我们一起深入了解 c 加加里的基础函数, 这部分内容还是很重要的,那我们先来看看函数的定义,就 c 加加里面函数的定义都有哪些不 和或缺的组成部分?呃,一个完整的函数定义,它是包括返回类型、函数名称,然后参数列表就是行参列表,还有函数体这四个部分。那返回类型就是这个函数运行结束之后,它会返回一个什么类型的数据, 函数名称就是我们后面会用来调用这个函数的名字,然后行参列表就是放在括号里面的,它定义了我们要传进来哪些参数,这些参数是什么类型的,然后有几个。 最后函数体就是放在花括号里面的,具体的实现这个函数功能的一系列的语句。没错,那你能不能讲一讲函数的调用, 以及在调用过程当中,这个时餐和行餐之间是怎么传递数据的?当然可以,其实在调用一个函数的时候呢,是在函数名后面加上一对圆括号, 然后这个圆括号就相当于是一个执行的开关,就是一遇到这个圆括号,程序就会跳转到这个函数体里面去执行。那时餐和行餐在这个过程当中是怎么配合的呢?是这样的, 行餐其实就是函数定义的时候声明的那些变量,它相当于是一个接口,用来接收外面传进来的数据。然后时餐就是我们在调用函数的时候,真正传递进去的那些具体的值。 对,然后在调用的那一刻,时餐的值会被拷贝一份给行餐。嗯,就这两者在内存里面是完全不同的两个空间,所以对行餐的修改是不会影响到时餐的。 ok, 那 紧接着我们要讲的就是通过一个代码示意来看看函数是怎么实现具体功能的。 比如说我们现在要写一个求结乘的函数,那这个函数的核心逻辑应该怎么设计?然后在 c 加里面怎么用代码来实现它?对,结乘其实就是从一一直乘到这个数本身嘛。那我们就可以用一个 while 循环来实现这个累乘,然后每次让这个数减一,直到它等于一为止, 最后返回这个累成的结果。嗯,你能具体讲一下代码怎么写吗?问题。比如说我们可以这样写, in fact, 然后在函数里面呢,我们先定义一个变量, rat 等于一,这个就是用来保存我们累成的结果的,然后 while 括号 val 大 于一,那我们就不断地让 rat 乘以 val, 然后 val 再自减一,嗯, 最后 return write, 这样就可以了。听起来很简单啊,那我们写一个 mean 函数来测试一下这个阶乘函数。比如说我们想求五的阶乘,那这个代码应该怎么写?很简单,你就直接在 main 函数里面定义一个变量,比如说 into j 等于 fact 五,然后你把 j 输出一下就可以了, 这个时候 j 的 值就是一百二十,就是五的阶乘的结果。明白了,那我们现在来聊一聊函数作用域里面的局部对象。嗯,那你能不能给我们讲一讲 局部变量的生命周期和它的出场规则。呃,局部对象其实就是在函数的行参或者是在函数体里面定义的普通变量, 然后它的生命周期呢?就是从这个程序执行到它的定义那一行开始,然后到包含它的这个代码块结束,它就被销毁了。那如果这个局部变量我们没有手动给它出场化,会发生什么?如果是一个内置类型的,然后它的值就是未定义的,就是一个随机值, 这个时候你去使用它的话,就很容易产生一些难以发现的错误。是的,所以说局部静态对象它到底有什么特殊的地方? 局部静态对象就是你在一个函数内部定义变量的时候,前面加上一个 static 关键字,那这个变量就只会在第一次执行到这个定义的时候被促使化, 然后它的生命周期会一直持续到整个程序结束,即使函数返回了下一次函数退出的时候的时候的值。 那这个特性是不是就特别适合那种需要记录函数被调用了多少次这样的场景?没错没错,你可以用一个局部静态的 size t 类型的变量,然后每次函数被调用的时候就自增一,然后返回这个值,这样就可以记录总共被调用了多少次,就算函数退出,这个值也会被保留。听起来很有用啊, 那函数声明到底是个什么东西?为什么我们有时候在调用函数之前一定要先声明?因为 c 家的变易器是从上到下顺序变异的,然后他又要求你在使用一个函数之前必须要先声明。那如果你把函数的定义写在了调用之后,那变易器在遇到这个函数调用的时候,他是不知道这个函数长什么样子的, 所以你必须要在上面先声明一下这个函数,也就是说函数声明其实就是告诉编辑器这个函数的名字,返回类型,还有参数的情况,对不对?没错,函数声明就是也叫函数原型嘛,它就是写一个函数的返回类型,函数名,然后参数的类型顺序个数, 但是它没有函数体,就是没有后面的花括号和里面的实现的代码。那函数声明在写代码的时候一般会写在什么地方?一般我们会把函数声明写在头文件里面,就是以点 h 为后缀的文件里面,然后这个头文件会被其他的原文件包含进去,这样的话在整个项目里面的其他地方都可以用这个函数了。 好的,然后我们接下来要聊的是一个非常重要的概念,就是分离式翻译。对,那你能不能先给大家讲一讲什么是分离式翻译?其实分离式翻译就是说你可以把你的程序分成多个文件, 然后每个文件都可以单独的去编写和翻译,最后再把它们链接在一起,就生成了一个可执行程序,就相当于你有很多主拣,你每一卷都可以单独的书。那在实际操作的时候,这个分离式翻译到底是怎么一步一步做的? 首先你要创建一个头文件,就是以点 h 结尾的,然后把你要用到的函数的声明都放在这个头文件里面。接着你再创建一个源文件,就是以点 c p p 结尾的,然后把这个函数的具体实现的代码写在这个点 c p p 文件里面。 然后接下来就是编辑和链接这两个步骤了吧。然后你就用编辑器去单独的编辑每一个点 c p p 文件,它就会生成一个对应的目标文件,就是以点 o 为后缀的文件。 最后你再用链接器把所有的这些目标文件和你需要的一些库文件链接在一起,就生成了一个可执行文件。好的,简单总结一下, 函数四要素实参到行参,默认是拷贝自动对象,随函数创建销毁静态对象全程存活声明放头文件,大型项目用分离翻译,掌握这些函数基础就稳了。今天的内容就到这里,我们下期再见,拜拜!

大家好,我是王一山,今天我想给大家分享一个程序,这个程序呢就是一个颠倒了英文的字母,比如你来输入一个 abc, 它就会反过来输出 c、 b、 a, 你 输入一个数字五六七,它反过来就是七六五。 然后呢我在想,如果我输入一个汉字会怎么样?一般 c 加加呀,他是不支持输入汉字的,如果你输入一个汉字,他很可能出现一些数字啊,乱码呀之类的。 比如我输一个王,我们来看看他会说出什么呀?咦,怎么说出了一个这个汉字?那如果我不只输入一个汉字,我输一个,你好, 还有输输出了,这个发现没有?是不是感觉很有趣,却有点摸不着头?然后我问了一下 ai, ai 帮我解答了一下, 身为在 windows 系统和大多数中文环境下呀,它中文制服通常使用 g、 b、 k 编码或者 utf 杠八编码,而不是 x 编码, 这个环境使用的是 g、 b、 k 编码。比如说出你它的 g、 b、 k 十六禁制编码是 c 四一三好是 b a、 c 三, 它的这个连起来就是 c 四一三 b a、 c 三,反过来 c 三、 b a 到这一三到这 c 四,到这 c 三 b a 一 三 c 四,然后混合在一起就变成了这两个汉字。 所以它这个呢,就是用的 g、 b、 k 编码进行反转, 这相当于我们多了个什么呢?我们多了个中文的加密软件,比如星期三去玩, 我们就可以进行给它加密,就是这个东西一个乱码,中间有个问号显示不出来,我们把这个复制出来, 我们再进行输入,我们就把它解密了,就是星期三去玩,大家觉得这个程序有趣吗?

哈喽,大家好,这一课我们来一起了解一下选择结构里边的 switch 语 句。 switch 语句它是一个多选项的分支结构,既然是多选项,这就意味着我们再去写表达式的时候,可能不仅仅是写一个,而是要去写多个,然后呢根据这个表达式来决定要执行哪一个代码块。 而这个功能呢,之前我们也了解过类似的语法,就比如说咱们用过一个东西叫做 if, 然后 else if 后边的话呢,如果说有其他的选项的话,我们还可以加上 else if, 那 如果说没有其他选项了,我们可以加增加上一个 else 语句,是吧?这样一个形式,它的话呢也是一个多选项的分支结构, 而我们这个 switch 跟我们之前学过的这个语句的有什么区别呢?我们可以把这个 switch 呢理解成这个的话呢,就是一个简化版, 那它是怎么简化的呢?我们来一起去详细的去看一下啊。好,那么这个东西啊,就会涉及到它的一个语法的问题,如果说啊,咱们想要去使用它,首先我们要去写一个思维词,关键字后边的话呢加上一个括号, 这个括号里边的话呢就是它一个具体的表达式,那这个表达式后边紧跟上一个花括号,花括号里边有这个 case, 这个 case 后边的话就写这个值,这个值就是我们要去使用或者是匹配的那个具体的那个值了,那么当它匹配上了以后, ok, 那 么这时候的话呢,就可以执行里边这个语句了, 发现在这里边还有一个香的关键字叫做 break, 对 吧?那这个 break 的 话呢,就是决定我们是否要去退出咱们这个相应的这个,哎,多选的这个功能, ok 吧?好,那么具体的话呢,在底下我还写了一些香的文字来去解释,我们来一起去看一下啊。首先 switch 的 话呢,后边有一个表达式, 这个表达式是用来干什么的呢?它是用来决定我们要去执行哪一个代码块的啊?就比如说我们这写了一个表达式,表达式呢,他的一个结果的话呢,是一个数字一, ok, 好, 那么拿到这个数字一以后,他会做什么事情呢? 他会去根据这个值上这个括号里边进行相应的去匹配,因为你会发现这个值上这个值一,这有个值二。后边的话呢,我们还可能会写更多的一些相应的这个值, 只要是这个值跟这个上面表达是哎,正好相等,正好相匹配,那么这时候说明什么呀? 说明他已经知道要去执行哪一个了,那么当匹配上了以后,他就会执行对应的这个相应的这个语句块。好,那么当他执行完这个语句块以后,一碰到 break 成,那么这时候的话呢,他就退出了咱们这个多选的这个功能了, ok 吧?好,那么这是什么呀?这是咱们说的是 匹配上了,对不对?好,那么如果说没有匹配以上的话,那怎么办呢?那这时候的话呢,他就可以走这个什么有一个 default 语句, default 的 语句是什么?就是默认语句,意味着如果说什么东西都匹配不上,那么我们就执行这个语句,他呢就类似于我们 if else 里边这个 else 啊,就是你什么东西都匹配,这个都满足不了,好,那么我们就走 else 这个这个语句就可以了,是这个意思,类似于他,好吧,好,那么在这的话呢,我们要特别去说明的啊,有一些东西,首先第一 这个 default 的 话呢,这个 default 呢,虽说是作为默认值,但是的话呢,这个顺序上来说的话呢,它并不是说一定要去写到最后,我们可以把它穿插到上面来啊,也是没有问题的,它不会去影响咱们这个代码的一个功能, ok 吧?好,那除它以外的话呢,还有就是这里边的话呢,有一个关键字叫做 break, 好, 那这个 break 的 话呢,它其实就是代表了要退出我们当前这个选择结构, 那如果说咱们不加这个 break 款,那他,那他会出现什么样情况呢?比如说我们现在的话表达式这有个一,这表达式给他写了个一,好,那么他正好匹配上第一个了,第一个以后的话呢,这恰巧又没有 break, 那 么好,这时候会出现什么情况呢?他会执行完这个语句以后,然后再执行 这个第二个,这里边的那有小伙伴可能就想了,说,那他没匹配上,他怎么能走这块呢?是因为咱们这的话呢,没有去写 break 说,哎,我这个执行完代码块要退出, 那么他就会直接把下边所有的这个语句块挨着牌去执行,那么执行到什么程度算结束呢?当他看到这个 break 的 时候,看到这第一个 break 的 以后,那么他就会去结束,他是这样子去运行的, ok 吧?好,那么这个运行流程啊,咱们一定要清楚啊。好,那么除这以外的话呢,然后底下的话呢,我还写了一些其他的啊,那么还有一个就是什么?就是我们这个表达式的问题, 那这个表达式的话呢,我们这看嘛,这这个表达式它这个值的类型的话呢,并不能随便去写啊,并不能去随便去写。那么咱们之前用这个 ifelse 的 时候,咱们可以什么去?让它去返回一个布尔值,对不对?那它这的话呢,也是同样不能去随便去写,它只能去啊,它的结果只能是一个 int 类型、差类型、 shift 类型或者是浪类型, 其实你会发现它归根结底是什么呀?就是数字类型也是可以的啊。好,那它是不支持赋点和字母串的。 好,除它以外的话呢,还有就是这个 case 里边这个值的话呢,哎,不能重复,那不能重复是什么意思?你比如说这一个表达式是一个一,这个一的话,然后匹配这个匹配上了,下个的话呢,又能匹配上了,这肯定不合适啊,对不对?所以说的话呢,哎,这这个值啊,是不允许重 重复的, ok 吧?好,那么这搞定了以后,还有就是这里边这个代码块的话呢,如果说有一个啊,那么我们可以省略这里边的花括号,如果说没,如果多一个代码块,多个代码的话,那么我们就要推荐给大家用这个花括号给它扩起来,这样的话呢,还会更直观,增加了这个可读性, ok 吧?好,那么这是这块啊, 成,那么了解完这个东西以后的话呢,关于这个 switch 的 一个基本使用,咱们基本上就咱说完了啊,那么接下来的话呢,我们再来通过代码去看一下它的具体效果啊,这样的话呢,可以加深我们的印象。 好,那么我们可以看到我在这的话呢,已经提前创建好了一个文件,叫做 switch 多分之结构,对吧?好,那么里边的话呢,也写了一些代码,首先的话呢,我们这边去引入了头文件和这个相同的一个声明,后边的话呢就是入口函数,入口函数的话呢,这里边写上一个就是啊,这个需求 啊,需求是什么呢?去输入一到七的啊,整数啊,整数啊,整数,然后让他去输出什么呢?输出对应的星期, 比如说我们输入一,那么他就会输出星期一,然后如,如果说是二的话,那么他就输出星期二, ok 吧?是这个意思啊。好,那在这的话呢,我们看一下这个代码这个逻辑啊,首先这定一个叫做 number, 这个 number 的 话呢,它是用来去接收咱们输入的这个数据的,对吧?我们可以看到他在这给他进行一下的一个接收,接收完了以后的话呢,注意他把这个值的话呢放到哪了? 放到 switch 的 这个表达式里边来了,咱们之前说了,这个表达式里边他是不是只能是什么?哎,整数 啊,整数啊,整数,说是整数的话,其实说白就是 int 浪尺尺什么这些东西,对不对?然后并且的话呢?哎,还,还有就是一个美举啊,那么我们在这的话呢,就全是整数了,就不用说了,对吧? 好,那么这搞定了以后,那么也就说他应该是范围是一到七,对不对?好,那么比如说啊,比如说的话呢,他是一个输入了一个数字一,那么好,那么当我们去往下去走代码时候,他会看看 它匹配到谁啊?匹配到一了,那么这时候它就会跟我们去输入谁啊?输入 monday, 对 吧?输入这个东西, ok, 好, 那么输出完了以后,那这时候它会怎么去做呢?它这个东西啊,因为代码你看可以看到这里边的话呢,我们并没有去写 break 那 个关键字,对不对?所以说的话,它会依次的把后边的这个跟我们进行,相当于一个输出挨着牌去走一遍, 那么当他走完了以后, ok 程序就算是结束了,就这个意思, ok 吧,好,那么这是这块,那如果说他输入的是一个数字二的话,那么他会出现什么情况呢?他第一个没匹配上,对不对?那么好?第二个匹配上了,那么就从这开始打印往下意思去执行。 那如果说我们输入的是七的话,好,那么前面都没有匹配上,只有匹配这一个,那么他只会输出这一个, ok 吧?好,是这个意思啊,好,那么我们知道他一个具体的一个结果以后,那么接下来我们来看一下他的他这个效果是不是跟我们想象的一样啊? 比如说我们输入的是一个数字一,数字一的话,他应该是输入这个,哎,从星期一到星期天挨着牌给我们去进行相同的输出,对不对?那你会发现这是七个全都给我们去输出了,好,那么这是这样情况,那比如说我现在的话呢?输出的是二二的话,那么他应该什么呀?从星期二到星期天挨着牌给我们进行输出,对不对?是这个意思, 好,那么咱们说了,如果说像是输出的星期七的话啊,七的话,那么他就最后一个,这是不是咱们之前了解过的?比如说当他匹配到了一个以后,从这开始,以下所有的挨着牌的给我们进行一个执行,对不对?好,那么这是这块啊, 成,那么问题是咱们既然说是多分值了,所以所以说的话呢,这里边这个语句块的话呢,并不代表是所有的东西都要进行相同执行,对不对?他要根据不同的值来去执行指定的一个代码块就可以了,其他的就不要再去执行了, 那面对这样一个情况应该怎么办呢?好,那么我们就需要在这里面去给它增加上一个关键字啊,加上加上一个叫做 break, 我 们把这个 break 的 话呢,给它去加上来啊,这个 break 的 话呢,我们可以理解成这也是一个语句, ok 吧?啊?也加上一个语句, 好,那么加上这个语句了以后,然后接下来我们再来去运行, 运行以后,然后我们可以看到,比如说我输入一个数字,一一敲回车,你会发现看到吗?只输出了这个星期一的这个英文单词,对不对?然后我们再去输出,哎,比如说我输出星期六, ok, 你 会发现它只是一个英文单词,这就什么呀? break 的 一个优势啊,有不能说是优势,把它的一个功能 break 就是 退出当前结构, break 退出当前的结构啊,那么这个结构的话,就是我们这个选择结构了, ok 吧?好,那么这是这块,好,那除他以外的话呢?然后还有一个就是星期天的话,你觉得这个地方我们还有必要,有没有必要去写啊?答案是时间来说的话,因为他本来就是最后一个了,所以说写不写已经无所谓了, 对不对?好,那么这是这个东西好,除这以外的话呢?还有就是如果说我们这 case 的 话,这比如,比如说这有两个代码块,那我能不能用这个花块号给它括起来呢?那你觉得这样去写行不行?我们给它括起来啊? 看一下,那这样的话它能不能跟我们去执行过去呢?然后我们在这去点运行啊?点运行以后我们选择一,你看这是不是也没有问题啊? 那么也就是说,如果说以后我们这这个代码块内容是比较多的时候,我们可以尝试着去增加这种画括号来去增加我们这个代码的这个可读性, ok 吧?好,当然我们也可以通过缩进的方式进行一个编写啊,只是说我们增加画括号的话呢,可能这个可读性会更高一点啊,这是这块好, 除它以外的话呢?还有一种情况,现在的话,我们输入的这个数字要求是一到七,对不对?那么并且的话呢,我们这这个值也给他去设定好了,就比如说我现在的话呢,我就故意啊,输入一个数字八,那么一敲回车,你会发现他什么也就不输出了, 那么什么也不输出的话,那么是不是就会有问题啊?就感觉咱们这个程序好像已经坏掉了,或者是有 bug, 对 不对?那么这时候我们怎么办呢?哎,我们就可以考虑换种方式,我们加上一个,什么叫加上一个叫做 default, 加上这个值,好,那么我们加上这个值以后告诉他,哎,输出啊,输入错误就可以了。你说如果说有这种,哎, 意料之外的,咱们这个这个选项意料之外的,那么好,我们这时候呢,给他告诉他输入错误就可以了,好吧?好,那么在这的话呢,我们告诉他,比如说我输入一个数字八,一切回车,你看他输入错误,对吧?这就是什么呀?这个 default 的 一个使用,也就是说默认情况来说,他就会走这个 ok 吧?好,那么还有就是我们去修改它,比如说我把它呢给它放到上面来,放到上面来。 好,那么我们把它放到上面来以后,然后我们再点击运行,那再点击运行,点击运行以后,然后我们再去输入数字八,你会发现这的话呢,又出现这个问题了,那么他出现这个问题说什么输入错误,然后再加上了一个星期天,那么为什么输入星期天?因为你会发现 咱们当他去匹配上了以后,然后你会发现下边的话呢?并没有什么呀?没有 break, 所以 说他后边这个数据继续会给我们进行执行,所以说在这的话呢,我们也要加上这个 break, 对 不对?好,那么他写完了以后,然后 ok, 然后在这我们再去输入星期天,也就说咱们现在的话呢,这个这个 default 它是不是在七上面?那么好,我们直接去输入这个星期天,看看他能不能跟我们去匹配到。 ok, 那 么这时候你会发现看到吗?效果是一样的,它不会说什么说,哎,我现在的话呢,从上到下上面的话都没有匹配上,然后我们就走这个 default 吧,并不会,它会什么呀?它会把这二维码的跟我们进行匹配一遍,然后发现都不是的时候,然后才去走这个语句, ok 吧?好,这个咱们一定要清楚啊。 好,那么这聊完了以后的话呢,关于这个 switch 的 一个使用方式,我们基本上就算是说完了啊。 好,接下来的话呢,我们来我们来看一个练习题,在 c 语言中,对于 switch 结构说法正确的是 switch 中 case 选项可以是多个,对吧?这是没问题,正因为它可以写多个,所以说的话呢,我们可以把它理解成是一个多分值的选择结构,对吧?好,那么 switch 选择结构可以平替,一夫 选择啊, if 的 这种选择结构,答案是,这个东西也不能说是完全平替,但是他大部分情况是可以的,所以说这个还是有一点点的出入的,因为你会发现我们在这去输入这个值,它是什么呀?它是可以任意多个相等的数值的, 而咱们 if else 那 种里边的话呢,它只能什么?就是,哎,一二就是零,零和一的结果的值是零和一,但是条件的话呢,我们可以写的更丰富一些,对不对? 那么这个东西就根据我们这个具体使用情况了,如果说我们选择的我们那个后期的一个条件是比较丰富的话,用 if else 的 话呢,可能会描述的会更清楚一些啊,好,那这是这一块,还有就是 switch 的 中的话呢,它是必须使用 default 关键字,并不是这样子,只是说添加它了以后的话呢,会更加的友好。 哎,可以想象的,可以什么呀?可以避免一些我们想象不到的一些值,这样的话呢,它同样是能帮助我们进行处理,对吧?好,这是这一块,然后 switch 中匹配了 case 下边这个代码块,并不是的, 它当它去找到这个代码块以后,它会什么呀?如果说没有发现 break 的 话,它会依次地向下去进行这样的一个执行,对吧?因此的话,这道题正确的选谁呢?哎,我们选择 a 就 可以了啊。

从新手到面向对象高手,第一步就是写好类,为什么别人的类清晰安全,你的却混乱易错?今天带你吃透抽象数据类型的核心。我们 先来说说什么是抽象数据类型?它的核心概念是什么?它到底是怎么把数据和操作捆绑在一起的?抽象数据类型其实就是把数据和操作数据的函数打包成一个整体,然后只暴露出一些统一的接口,至于具体是怎么实现的,外面是看不到的。 这样做的话就可以让使用这个数据类型的人不用关心内部的细节,只需要知道能做什么操作就行。明白了, 那数据抽象和封装性在抽象数据类型里面到底扮演一个什么样的角色?数据抽象其实就是把接口和实线分开,让他们之间的依赖变小。 而封装性就是把数据和操作绑在一起,然后保护内部的状态不被随意改变。比如我们生活中的日期,日期里面有年月日,然后他还有一些操作,比如说获取当前日期,设置新日期,比较两个日期的早晚。 这些东西都是对外隐藏的,你只能通过它规定的方法来访问和修改。那这个 sales data 类到底要怎么设计才能满足书籍销售数据的这些需求?我们首先要明确我们要设计的这个类要包含哪些核心的数据,像书的编号、 isbn、 销售的数量、销售的金额,这些肯定是要有的。 然后我们要把这些数据和对这些数据的操作放到一个类里面,这样的话整个关于书的销售的信息就都有一个统一的管理了。具体来说的话,这个类要提供哪些方法才能让外部去访问和修改这些销售数据呢?比如说我们可以定义一个 sbn 函数,用来获取 sbn 编号, 然后定义一个 combine 函数,用来把两个销售记录合并。 add 函数用来把两个销售对象相加。 read 函数用来从输入流里面读入数据。 print 函数用来把销售信息输出到输出流里面。懂了懂了,那我们如果要实际使用这个 sales default 类的话,具体该怎么创建对象?怎么去调用这些成员函数呢?创建对象其实很简单,就像定义一个 int 或者 double 类型的变量一样,直接用类名定义就行。 要用成员函数的话,就是用点儿愿算符,如果是通过指征访问的话,就用箭头愿算符。有没有什么具体的代码例子可以让我们看一下这个 sales data 类到底该怎么用?有啊,比如说我们可以先定义两个对象,一个用来存当前的总和,一个用来存新投入的交易。 然后我们可以用 read 函数从标准输入里面读入第一笔交易,如果读入成功的话,我们就进入一个循环,在这个循环里面我们不断地读入新的交易。每读入一条,我们就用 a, s, b, n 函数检查是不是同一本书,如果是的话,就用 combine 函数把它合并到总和里面,如果不是的话,就输出当前的总和,然后处理下一本书。 最后如果什么都没有输入的话,我们还要处理一下这种特殊情况。好,那我们在定义 cs 下划线 data 这个类的时候, 在内里面的成员函数具体要怎么声明?然后内外面的那些非成员接口函数又要怎么声明?在内里面的话,我们要声明 s b n 函数、 combine 函数,还有 f g g 下划线、 price 函数,然后还要定义书号、销售量和收入这几个成员变量。 类外面的话就是要声明 add, print 和 read 这三个函数,这些函数都是属于这个类的接口的一部分,但是它们不是成员函数。我还有一个问题啊,就是这个成员函数到底是怎么定义的?它和普通的函数有什么区别? 成员函数其实就是定义在内里面的函数,它可以直接访问类的所有成员,普通函数就没有这个权限。 还有一个特别的地方,就是每个非静态的成员函数都有一个隐藏的 diss 指征,它指向调用这个函数的对象。还有一个点,就是这个 const 成员函数 它到底是个什么东西?然后它的这个承诺到底意味着什么? const 的 成员函数就是在参数列表后面加上 const 的 关键字,它向外界承诺,在这个函数内部不会修改调用它的对象的状态。比如我们之前那个 sbn 函数,其实它的完整的形式应该是这样的, 虽然在类里声明的 sbn 成员函数的参数列表为空,但实际上它有一个隐藏的指向当前调用该成员函数的对象的指征。因为声明的时候使用了 const 限制了函数,所以这里的参数也受到了 const 限制。只不过这个 this 指征是编辑器帮我们自动生成的,我们没有办法自己写出来 了解了。至于为什么要将 add, print 这些设置为非成员函数接口,这实际上是设计决策的问题,只是为了更符合使用习惯。设计的时候可以参考 int, double 这些内置类型,或是 string 这样的标准库类型。那类的成员函数到底都有哪几种定义方式?然后在内外面定义成员函数的时候,有什么特别要注意的地方吗?成员函数可以直接在内的里面定义, 这样的话编辑器会自动把它当成一个内联函数来处理。也可以只在内里面写函数的声明,然后在内的外面把函数实现出来。 如果是在内的外面实现的话,就必须要加上类名和两个冒号,用来指明这个函数是属于哪个类的,不然的话编辑器就会报错。 比如说我们那个 aggregate 下划线 press 函数在外面实现的时候,就要写成 double cells underscore data, v g underscore press const 这样好,那我们这个 sales data 类里面如果想要实现类似于加这样的操作, 具体应该怎么通过这个 combine 成员函数来实现呢?我们可以让 combine 函数返回一个对当前对象的引用,然后在函数题里面把另一个对象的数据成员加到当前对象上,最后返回这次时针解应用之后的结果就可以了。原来是这样啊, 那像 read print 和 add 这种跟 sales data 紧密相关,但又不是成员函数的函数,我们应该怎么去定义和声明呢? 这些函数虽然不是成员函数,但是它们是类的接口的一部分,所以一般会和类的声明放在同一个头文件里面, 然后像 read 函数,它是接受一个输入流和一个 sales data 的 对象的引用,它会从这个流里面读入数据,然后设置到这个对象里面。 print 函数的话是把对象的内容输出到一个输出流里面。 add 函数的话,是把两个 sales jet 的 对象相加,然后返回一个新的对象,表示它们的和。这里要注意的一点就是,因为流对象是不可以拷贝的,所以我们只能通过引用来传递它们。 然后如果我们要在函数里面修改流对象的话,这个参数是不能用底层 const 的。 懂了懂了,那我们接下来要聊的这个构造函数在一个类里面到底扮演一个什么样的角色? 然后它在语法上和普通的成员函数有哪些不一样的地方?构造函数其实就是一个特殊的成员函数,它的名字和类名是一样的,然后没有返回类型,它的作用就是在创建对象的时候去促使化对象的数据。成员 构造函数是可以有多个重载的版本的,这样的话我们就可以用不同的方式去促使化对象。但是有一点要注意,构造函数不能用 const 来修饰,因为在构造函数完成之前,这个对象还没有真正地变成一个敞亮对象。那在我们没有自己定义任何构造函数的情况下, 编辑器会在什么情况下帮我们生成一个默认构造函数?然后它又是怎么初识化类的数据成员的呢?只有在这个类,没有声明任何构造函数,并且所有的类类型的成员都有自己的默认构造函数的时候,编辑器才会自动的帮我们生成一个默认构造函数, 这个时候它会按照这个成员在内里面申明的顺序依次地去出示化它们。如果这个成员有内内出示值的话,就用这个值来出示化,否则的话就进行默认出示化。能不能结合 sales 下划线 data 这个类, 讲一下我们要怎么去定义多个构造函数,让它可以分别去处理不同的抽象的情况。当然可以,比如我们可以定义一个默认的构造函数,让它使用 default 关键字来生成默认行为。然后我们再定义一个构造函数,它接受一个 string 类型的参数,用来促使化 booknote 还有一个构造函数,它接受 string, onset 和 double 三个参数分别用来促使化 booknote units 下划线 sold 和 revenue。 最后我们再定义一个构造函数,它接受一个 extreme 类型的参数,然后它会调用 read 函数从流里面读取数据来促使化对象。如果我们想要在构造函数的定义里面去使用 extreme 类型的参数来读入数据,并促使化对象,具体要怎么实现呢? 这个的话我们就直接在函数体里面调用那个 read 函数,然后把这个 stream 对 象和 this 指向传进去就可以了,这样的话这个对象就会从输入流里面读取一条交易信息,然后用这些数据来促使化自己。 好,然后我们要讲的就是拷贝赋值和 c g 这三个部分。在我们这个 sales data 里面,对象之间的赋值到底是怎么逐成员进行呢?举个例子,如果我们有两个对象, total 和 trance, 当我们把 trans 赋值给 total 的 时候,其实是 total 的 每一个数据成员都被 trans 对 应的成员给依次赋值了一遍。明白了,那是不是所有的类都可以直接用编辑器默认生成的这个复制行为呢?一般如果这个类里面是管理动态内存的,就不能直接依赖编辑器自动生成的这个复制操作, 除非这个类里面用的是 vector 或者 string 这种会自己关联内存的类型。好的,今天我们把抽象数据类型的概念和 c 加加的类成员函数、构造函数,还有对象的拷贝和赋值都串起来讲了一下, 大家应该对如何设计一个类,并且隐藏实现细节有了一个更清晰的认识。行,那我们下次再见,拜拜。拜拜。

c 家家里如何处理一大段混着姓名电话数字的文本?今天教你一招用 stream 流轻松搞定。我们首先要聊的就是什么是 stream 流?其实说白了就是用 stream 来模拟一个 i o 设备。 对,那我们到底该怎么去理解这个东西呢?可以把 stream stream 当成一个类似于文件或者标准输入输出的一个东西,但是它操作的对象是在内存里面的字复串。哦,就是你可以把东西写到这个字复串里面,也可以从这个字复串里面读出来。哎,那这里面就有一个问题了啊,就是这个 stream stream 它有哪些特有的构造函数和成员函数, 这些东西都有什么作用?呃,它最基本的就是有一个默认的构造函数,就是你可以创建一个 stream stream 的 对象,但是它没有跟任何的字复串关联。 然后还有一个就是你可以直接用一个 stream 来促使化一个 stream stream 的 对象听起来就很方便啊。那除此之外呢,还有什么别的常用的成员函数吗?当然有了, 比如说 str 这个函数,就是可以让你得到这个流里面所关联的这个字串的拷贝,还可以通过一个 stream 对 象作为参数的 str 函数,将参数的内容拷贝到流对象中,而且会覆盖掉原来的内容。行,了解完这些啊,我们再来说说 stream stream 它到底是用来干嘛的?为什么我们要在解析结构化文本的时候要选它 istreamstream, 就是 当你有一行文本,它是有多个单词或者说多个数字,然后它是用空格分开的, 你想要一个一个地把它处理掉,那这个时候用 istreamstream 就 会非常的方便,因为它可以让你直接像 sing 一 样地去把这些东西一个一个地提取出来。能不能举个例子说明一下, istreamstream 到底是怎么一步一步地把一行文本拆分成一个一个的单词或者说数据项的? 首先你就是要用 getline 把一整行读进来,放到一个 string 里面,然后你把这个 string 交给 isstring, 接着你就可以像你从标准输入读数据一样,把它一个一个地读出来,它会自动地以空格作为分格符。嗯,了解了它的用法,那下面咱们来看一下具体的代码实现吧。 就比如说我们有这样的一些数据,它是一些个人信息,包括名字和电话号码,然后我们想要把它解析成一个一个的对象,那这个代码该怎么写呢? ok, 我 们首先要定义一个结构体,这个结构体里面有一个 string list 的 name 和一个 vector string list 的 phones 来分别存放名字和电话号码。 接着我们定义两个变量,一个是 line, 用来存每一行的输入,另一个是 word, 用来临时存放解析出来的单词。然后我们定义一个 vector, 用来存放所有的个人信息。嗯,然后呢 就是怎么把每一行的数据再细分。我们在一个 while 循环里面用 getline 整行读入数据,然后在循环体里面,我们先创建一个 isstream 对 象,把这一行数据放进去,接着用这个对象依次把名字和电话号码提取出来,最后把这一条记录完整地添加到 people 这个 vector 里面。 由于一个人可能有多个电话号码,所以处理电话号码的时候需要使用 while 循环。好的,那我们再来说说这个 ostreamstream, 它主要是用来做什么呢?它的核心的思路是什么? o string stream 其实就是当你要构建一个比较复杂的字幕串的时候,你可以先把各种类型的数据按照你想要的格式一点一点地塞到这个 o string stream 里面,然后它会帮你自动地格式化,并且拼接好。懂了,那我们还是以处理电话号码为例吧, 比如说我们现在有一个 people 的 列表,然后我们要去便利这个列表,对每一个人的信息我们都要去便利他的电话号码列表。然后呢,我们就创建两个 ostream stream, 一个叫 formatted, 一个叫 bad nums, 分 别用来存放格式化后的有效号码和无效号码。具体怎么判断和区分有效无效号码,然后怎么把它们分别放到不同的流里面呢?在循环里面呢,我们就去检查每一个号码,如果这个号码是无效的,我们就把它放到 bad nums 里面, 如果是有效的,我们就先格式化一下,然后放到 format 里面。对,最后如果 bad nums 里面没有东西,就是 empty 等于 two, 那 就说明没有错误的号码,我们就可以直接把名字和格式化好的号码一起输出, 否则的话,我们就把错误的号码信息输出到标准错误流里面。明白了,那最后我们再来回顾一下,就是说 stream, stream 到底给我们的数据处理带来了哪些灵活性?其实 stream stream 它最大的好处就是它把自互串和这个 i o 流操作结合起来了, 所以我们可以在内存里面非常灵活地去转换和处理数据,而不需要去担心底层的一些细节。嗯,那这就使得很多文本解析啊,或者说自互串拼接啊这些任务变得非常的简单。 对,今天我们其实就是带大家认识了一下 c 加加里面的这个字幕串流,然后也通过一些例子给大家讲了一下它在数据处理和文本解析的时候的一些优势。好啦,咱们下次再见,拜拜!拜拜。

为什么修改了行餐,食餐却纹丝不动?为什么数组传给函数长度就消失了?所有答案都藏在这节课里,吃透 c 加加参数传递核心规则,让你的代码更高效,更健壮。 首先第一个话题啊,就是函数在调用的时候,参数传递的核心原则是什么?还有它的底层的逻辑是什么?其实在 c 家里面,函数的行餐的初使化 跟我们平时定义一个变量是一样的。对,他也是要先定义再出式化。那函数在调用的时候呢?变易器会用我们传入的时差去出式化函数定义里的行餐。明白了,那这个出式化的过程具体都有哪些方式呢?这个嘛,最常见的有两种方式,一种呢就是指拷贝, 就是我创建一个时餐的副本,然后把这个副本给行餐,那这样的话,行餐和时餐其实是两个完全不同的东西,你改一个对另一个没有影响。嗯哼,另一种呢是引用绑定,那这种方式下行餐,它其实就是时餐的一个别名, 他们两个其实指向的是同一块内存地址。了解了,那什么是传值参数?就是它的核心特点,以及它到底跟时餐之间是一个什么样的关系。当你把一个参数以值传递的方式传进函数的时候,其实函数内部操作的只是这个时餐的一个副本。对, 就相当于你拿这个时餐盖了一个章,然后你在这个章上面怎么图画,都不会影响到原来的那个东西哦。所以说函数对行餐的修改是完全碰不到外面的时餐的。是吗?完全没错, 因为行餐和时餐本身就是两个独立的个体。嗯,你在函数里面把行餐改的再天花乱坠, 时差的值该是什么还是什么? ok, 那 我们如果把一个指真作为参数传进去的话,在函数里面对这个指真和它所指向的对象分别做修改,会有什么样的不同的结果?举个例子,假如我们有一个函数,它的行餐是一个 int 类型的指真,那我们在函数内部 既可以通过解引用这个指真去改变它所指向的那个对象的值,嗯,也可以直接给这个指真 附一个新的地址,但是这两个操作的结果是不一样的,这么说的话,是不是意味着改那个对象的值是会影响到时餐的?但是你如果只是改这个指真本身对外面是没有影响的。对,因为你传进来的这个指真,它其实也是一个副本 啊,你改这个副本的指向,原来的那个指向是不会动的,但是你通过这个副本去改它所指向的那个值,嗯,外面是会变的。哎,那说到这我有个问题啊,就是船引用参数到底是个什么东西?它和船值相比到底有什么根本上的区别? 引用参数就有意思了,它其实就是给时餐起了一个别名,哦,它不是像船只那样弄一个副本出来,它就是直接跟时餐绑定在一起了。所以你在函数里面对这个行餐做的任何操作 都是直接反映到食材上面的。听起来这个引用传递还挺高效的。对啊,那它具体在性能上和使用上有哪些明显的优势呢?最大的好处就是对于大的对象,你不用再去花时间和空间去复制它了,你直接就是操作原对象,嗯,所以它会快很多, 而且你可以通过这个引用来修改外面的时差。哦,这样的话也可以很灵活的去实现一些数据的同步。确实是这样,那我们为什么要把函数的行参声明成函数的引用?这东西到底有什么好处?你想啊,如果我们的函数不会去修改这个传入的参数, 那我们把它声明成 cons 的 引用,第一它可以避免大对象的拷贝对,这样可以提高效率。第二呢,就是它可以很清楚地告诉调用者,我的这个函数是不会去动你的这个时差的。 ok, 这其实是一种很好的编程习惯。那如果我们现在要写一个函数去比较两个字母串的长度, 用 const 引用的方式来传参,这个函数应该怎么写?这个很简单,我们可以定义一个函数叫 is shorter, 功能是比较两个字母串的长度。函数的参数使用了 const string 引用类型,然后函数题里面就直接 return s, 一 点儿 size 小 于 s, 二点儿 size, ok, 这样的话就非常的安全而且高效,因为整个过程中完全没有任何的拷贝发生,然后也不用担心会把传入的字串改掉。好,我还有一个问题啊,就是为什么我们把数组作为参数传给函数的时候,其实传过去的是一个指真,因为 c 加它在处理数组参数的时候, 他不会真的把整个数组复制一份,他只会把数组第一个元素的地址传过去,所以函数里面接收到的其实是一个指真。所以说函数内部是不知道这个数组到底有多长的。对,那我们一般怎么来解决这个问题呢?一般我们会再增加一个参数,专门用来传递数组的长度 哦,这样函数才知道要处理多少个元素。原来是这样,那比如说我们有三种写法,一个是接受 constant into 星,一个是接受 constant into 方括号,一个是接受 constant into 方括号十,这三种写法在函数参数里面有什么区别吗? 其实这三种写法在编一系看来是完全一样的,它都会把它当成一个 const int 星,就是一个整型常量指数 哦,然后那个方括号里面的数字包括这个十只是一个提示,它在翻译的时候会直接被忽略掉哦,那我们接下来要说的是这个 main 函数的特殊行参,然后它们俩是怎么配合起来帮我们处理命令行参数的?其实 main 函数它有两个参数, 第一个参数它是一个整数,用来记录你这个命令行里面参数的个数哦。然后第二个参数是一个时针数组,它里面的每一个元素都是一个指向命令行参数字母串的时针。听起来好像 这个 rgb, 其实就像是一个数组,里面存了我们所有的参数的字符串,错了,没错了,然后这个 rgb 就是 告诉你这个数组里面有多少个元素哦,但是要注意,这个参数的第一个元素,也就是 argv 零,它是这个程序的名字, 所以后面才是真正的参数。我们来看一个例子,有一个程序的名字是 pro, 左边是一条命令行执行语句,内容是点斜杠 pro 空格杠 d 空格杠 o 空格 o 空格 data 零。 右边是它的解析结果,这里有两个关键变量, arg c 和 r g v。 首先 r g c 的 值是五,意思是总共有五个参数,包含程序名本身,再加上后面的四个参数。然后是 r g v 序组,它按顺序保存了每一个参数。 r g v 第零个元素就是程序名 pro, 后面四个元素是四个真正的命令行参数函数串,所以 r j c 记录了参数的总个数。阿根廷则按顺序保存了每一个参数函数串,这就是 c 加加中命令行参数的基本解析方式。 懂了懂了,那我们再说说可变形餐,就是当我们遇到这个参数的数量不确定的情况的时候, c 加到底给我们提供了什么样的解决方案?然后它一般用在什么场景下面? c 加里面,我们一般用 initializelist, 对, 它是一个模板类型,然后你用它的话,就可以直接传一个花括号括起来的列表, 比如说一串字母串或者一串整数。但是有一个要求,就是所有的时餐的类型必须是一样的。也就是说只要类型一致,我就可以用 initialize list 把它们打包成一个类似于数组一样的东西,然后在函数里面去便利它。对,因为引入 list, 它提供了 size, begin 和 end 的 这些方法,所以你可以很方便地去获取它的长度,然后也可以用迭代器去便利它。 ok, 而且它的使用也很简单直观。明白了,那如果我们现在要写一个函数,可以打印不同数量的 string 类型的错误信息,这个函数具体应该怎么写? 我们可以写一个名为 error msg 函数。这个函数接受一个 initialize 类型的参数,类型是 string。 函数体里用一个循环便利这个列表,从 begin 开头到 end 的 结尾,把每个元素依次输出,最后换行。在下面的调用式例中,当 expected 和 actual 这两个字母串不相等时,我们给 airs g 函数传入了三个字母串, function x, expected 的 值和 actual 的 值,如果相等,就传入 function x 和 o k 两个字互串。这就是 initialize 的 典型用法,它让我们可以一次性给函数传入任意多个同类型参数代码,更简洁也更灵活。 好啦,今天的参数传递核心知识点全部讲完了,理解底层逻辑才能写出健壮高效的 c 函数,我们下期再见!拜拜!