<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Posts on zhyDaDa的个人站点</title>
		<link>https://zhydada.github.io/posts/</link>
		<description>Recent content in Posts on zhyDaDa的个人站点</description>
		<generator>Hugo -- gohugo.io</generator>
		<language>en-us</language>
		<copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright>
		<lastBuildDate>Sat, 24 Jun 2023 23:04:26 +0800</lastBuildDate>
		<atom:link href="https://zhydada.github.io/posts/index.xml" rel="self" type="application/rss+xml" />
		
		<item>
			<title>不是很懂</title>
			<link>https://zhydada.github.io/posts/%E4%B8%8D%E6%98%AF%E5%BE%88%E6%87%82/</link>
			<pubDate>Sat, 24 Jun 2023 23:04:26 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E4%B8%8D%E6%98%AF%E5%BE%88%E6%87%82/</guid>
			<description>主要罗列一些不是很懂的问题，如有解答会补充 目录 前端 对元素的事件绑定 前端 对元素的事件绑定 对于同一个浏览器, 同一个网页, 同一个元素, 可以绑定cl</description>
			<content type="html"><![CDATA[<p>主要罗列一些不是很懂的问题，如有解答会补充
目录</p>
<ul>
<li><a href="#%E5%89%8D%E7%AB%AF">前端</a>
<ul>
<li><a href="#%E5%AF%B9%E5%85%83%E7%B4%A0%E7%9A%84%E4%BA%8B%E4%BB%B6%E7%BB%91%E5%AE%9A">对元素的事件绑定</a></li>
</ul>
</li>
</ul>
<h2 id="前端">前端</h2>
<h3 id="对元素的事件绑定">对元素的事件绑定</h3>
<ul>
<li>
<p>对于同一个浏览器, 同一个网页, 同一个元素, 可以绑定click事件, 但不能绑定dblclick<br>
有些网页两者皆可, 有些网页则偏偏不能dblclick</p>
</li>
<li>
<p>代码示例<br>
<code>$0.addEventListener(&quot;click&quot;, ()=&gt;{alert(1)})</code><br>
<code>$0.addEventListener(&quot;dblclick&quot;, ()=&gt;{alert(2)})</code></p>
</li>
<li>
<p>页面举例<br>
所有的微信文章均不可dblclick: <a href="https://mp.weixin.qq.com/s?__biz=MzI5MTQ5NDY1MA==&amp;mid=2247485037&amp;idx=1&amp;sn=1584cd593bfa2636163c91502fe206c6&amp;chksm=ec0e89f8db7900ee89c88f4b6be57ed9ab29113586b4b303d5d0aabda8edf8e7ba859ff2ca99&amp;scene=27">样例网页</a><br>
大部分网页还是两者均可的: <a href="https://www.jianshu.com/p/7a7133bcbb07">样例网页</a></p>
</li>
<li>
<p>问题补充<br>
对于一个元素, 可以在控制台查看绑定在其上的事件监视器<br>
在正常网页绑定click和dblclick事件后, 可以在控制台查看到两个事件<br>
但在微信文章中, dblclick事件绑定指令会被忽略(click和mousedown事件仍然有效), 似乎有针对性的屏蔽了dblclick事件</p>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>背书机v2</title>
			<link>https://zhydada.github.io/posts/%E8%83%8C%E4%B9%A6%E6%9C%BAv2/</link>
			<pubDate>Sat, 20 May 2023 08:47:16 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E8%83%8C%E4%B9%A6%E6%9C%BAv2/</guid>
			<description>目录 简述 亮点 待完成的一些功能 更新日志 借鉴的灵感和素材 简述 怀着激动的心情, 背书机v2已经初具雏形! 这一次主要的侧重点就在CSS 在动画上费尽心思</description>
			<content type="html"><![CDATA[<hr>
<p>目录</p>
<ul>
<li><a href="#%E7%AE%80%E8%BF%B0">简述</a></li>
<li><a href="#%E4%BA%AE%E7%82%B9">亮点</a></li>
<li><a href="#%E5%BE%85%E5%AE%8C%E6%88%90%E7%9A%84%E4%B8%80%E4%BA%9B%E5%8A%9F%E8%83%BD">待完成的一些功能</a></li>
<li><a href="#%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97">更新日志</a></li>
<li><a href="#%E5%80%9F%E9%89%B4%E7%9A%84%E7%81%B5%E6%84%9F%E5%92%8C%E7%B4%A0%E6%9D%90">借鉴的灵感和素材</a></li>
</ul>
<h2 id="简述">简述</h2>
<p>怀着激动的心情, 背书机v2已经初具雏形!<br>
这一次主要的侧重点就在CSS<br>
在动画上费尽心思, 最后的效果还是令人满意的<br>
点击右侧链接开始体验吧! -&gt; <a href="https://zhydada.github.io/EndorsementMachineV2/">背书机v2</a></p>
<h2 id="亮点">亮点</h2>
<ul>
<li>全新的排版布局, 明快的配色, 直观的操作方式</li>
<li>丰满的CSS动画设计, 舒适的操作体验</li>
<li>可以选择辞书, 可视化创建辞书</li>
<li>新增设置面板, 保留偏好设定</li>
<li>4款主题色供你选择</li>
</ul>
<h2 id="待完成的一些功能">待完成的一些功能</h2>
<ul>
<li>删除辞书</li>
<li>&ldquo;选择类型&quot;尚未制作</li>
<li>&ldquo;一言&quot;API导入</li>
<li>壁纸相关(设置API/下载壁纸/切换壁纸)</li>
<li>更简单易懂的输入格式</li>
<li>快速添加一个新的问题-答案组合</li>
<li>用户自定义主题色, 以及更多的配色</li>
<li>键盘快捷键</li>
</ul>
<h2 id="更新日志">更新日志</h2>
<ul>
<li>
<p>2023年3月23日</p>
<ul>
<li>表格式输入</li>
<li>格式化内容输入栏变为textarea</li>
<li>更多颜色</li>
<li>从&quot;池子&quot;中抽词</li>
</ul>
</li>
<li>
<p>2023年3月30日</p>
<ul>
<li>加入设置, 可以修改池子大小</li>
<li>两个按钮, 随心改变池子的配比</li>
<li>正则表达式, 更轻松的输入</li>
<li>表格式编辑的菜单栏采用sticky</li>
<li>准备搞一套深色模式和一言API</li>
</ul>
</li>
<li>
<p>2023年4月6日</p>
<ul>
<li>实现了问题的专属标志! 以问题字符串为原料生成一个唯一的图案辅助记忆</li>
<li>多个单词对比分栏呈现!</li>
<li>输入的格式更加简化, 会对输入预处理, 无需担心输入的是escape形式还是dom形式</li>
<li>实时反映问题频次</li>
<li>优化了全屏按钮(手机上没法实现double click, 还得是按钮来实现)</li>
<li>信息栏的CSS调整</li>
<li>准备让textarea也能全屏输入(实现方法和panel类似, 底部再加一个按钮, 进去之后的两个按钮: 退出全屏, 格式化)</li>
<li>说明部分还没改</li>
</ul>
</li>
<li>
<p>2023年4月27日</p>
<ul>
<li>去掉了未完成的全屏化</li>
<li>正则表达式再修改</li>
<li>专属标志再优化</li>
</ul>
</li>
<li>
<p>2023年5月20日</p>
<ul>
<li>标志再优化: 更居中 更大 更合适的比例 透明的颜色表现重叠效果</li>
<li>单词重复率记忆(但没有设置手动修改的地方, 下次在列表修改旁边再加一列, 否则有的单词变0就再也修改不了了, 同时辞书更新后重复率也要更新)</li>
<li>bug修补(因为pool没清空导致好几次新单词刷不出来)</li>
</ul>
</li>
</ul>
<h2 id="借鉴的灵感和素材">借鉴的灵感和素材</h2>
<p>主要来源是<a href="www.17sucai.com">17素材网</a></p>
<ul>
<li><a href="https://www.17sucai.com/pins/47729.html">页面模板</a></li>
<li><a href="https://www.jb51.net/jiaoben/827832.html#downintro2">hsycmsAlert弹窗插件</a></li>
<li><a href="https://www.17sucai.com/pins/45357.html">选择辞书的卡片式多选框</a></li>
<li><a href="https://www.17sucai.com/pins/43194.html">子标签</a></li>
<li><a href="https://www.17sucai.com/pins/44418.html">高级感按钮</a></li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>自定义油猴脚本</title>
			<link>https://zhydada.github.io/posts/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC/</link>
			<pubDate>Mon, 17 Apr 2023 09:38:34 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC/</guid>
			<description>快速连接: 自制超星刷课脚本 greasyfork油叉链接 目录 自定义脚本 脚本推荐 油猴脚本 自定义脚本 以下是本人自己写/修改的一些脚本, 从这些url</description>
			<content type="html"><![CDATA[<p>快速连接:</p>
<ul>
<li><a href="http://zhyDaDa.github.io/scripts/4.user.js">自制超星刷课脚本</a></li>
<li><a href="https://greasyfork.org/zh-CN/scripts/461448-zhydada-%E8%B6%85%E6%98%9F%E7%BD%91%E8%AF%BE%E5%8A%A9%E6%89%8B">greasyfork油叉链接</a></li>
</ul>
<hr>
<p>目录</p>
<ul>
<li><a href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%84%9A%E6%9C%AC">自定义脚本</a></li>
<li><a href="#%E8%84%9A%E6%9C%AC%E6%8E%A8%E8%8D%90">脚本推荐</a></li>
<li><a href="#%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC">油猴脚本</a></li>
</ul>
<hr>
<h2 id="自定义脚本">自定义脚本</h2>
<ul>
<li>以下是本人自己写/修改的一些脚本, 从这些url可以安装使用</li>
<li>由于要应对个性化需求, 有好的想法可以联系我, 尝试实现后发布上来供读者使用</li>
<li>编写脚本对js/css/html有一定要求, 本人只能触其皮毛, 仅以方便使用为目的</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">针对的网站</th>
<th style="text-align:center">用途说明</th>
<th style="text-align:center">脚本下载地址</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">zhyDaDa强力消杀</td>
<td style="text-align:center">1. 强力清除广告<br>2. 美化一些网站的排版<br>3. 实现一些&quot;免费&quot;</td>
<td style="text-align:center"><a href="http://zhyDaDa.github.io/scripts/1.user.js">1.user.js</a></td>
</tr>
<tr>
<td style="text-align:center">百度家族</td>
<td style="text-align:center">原脚本叫&quot;pure百度&quot;, 但因为其中有一些css上瑕疵, 故做出修改<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></td>
<td style="text-align:center"><a href="http://zhyDaDa.github.io/scripts/2.user.js">2.user.js</a></td>
</tr>
<tr>
<td style="text-align:center">华理网站登录系统</td>
<td style="text-align:center">在初次设定好用户名和密码之后, 以后无需手动登录, 还会自动关闭界面(手机端试验成功)</td>
<td style="text-align:center"><a href="http://zhyDaDa.github.io/scripts/3.user.js">3.user.js</a></td>
</tr>
<tr>
<td style="text-align:center">华理本研学习平台(超星脚本)</td>
<td style="text-align:center">除了不能做题其他都已经比较完善了</td>
<td style="text-align:center"><a href="http://zhyDaDa.github.io/scripts/4.user.js">4.user.js</a></td>
</tr>
</tbody>
</table>
<h2 id="脚本推荐">脚本推荐</h2>
<table>
<thead>
<tr>
<th style="text-align:center">针对的网站</th>
<th style="text-align:center">用途说明</th>
<th style="text-align:center">脚本下载地址</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">文库类</td>
<td style="text-align:center">打破文库类网站要登陆才能复制的局限, 但要注意复制时的格式可能会丢失</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/405130-%E6%96%87%E6%9C%AC%E9%80%89%E4%B8%AD%E5%A4%8D%E5%88%B6">🔥🔥🔥文本选中复制🔥🔥🔥</a></td>
</tr>
<tr>
<td style="text-align:center">百度网盘</td>
<td style="text-align:center">获取真实的下载地址, 配合IDM下载器直接起飞</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/436446-%E7%BD%91%E7%9B%98%E7%9B%B4%E9%93%BE%E4%B8%8B%E8%BD%BD%E5%8A%A9%E6%89%8B">网盘直链下载助手</a></td>
</tr>
<tr>
<td style="text-align:center">百度搜索页</td>
<td style="text-align:center">超多功能, 最好用的是去广告/双列排版/屏蔽部分网站/采用最直接的链接, 还可以自己设定功能</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/14178-ac-baidu-%E9%87%8D%E5%AE%9A%E5%90%91%E4%BC%98%E5%8C%96%E7%99%BE%E5%BA%A6%E6%90%9C%E7%8B%97%E8%B0%B7%E6%AD%8C%E5%BF%85%E5%BA%94%E6%90%9C%E7%B4%A2-favicon-%E5%8F%8C%E5%88%97">AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列</a></td>
</tr>
<tr>
<td style="text-align:center">各大网站</td>
<td style="text-align:center">真的很强力, 能直接下载大部分网站的收费内容, 知乎增强也很强<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/370634-%E6%87%92%E4%BA%BA%E4%B8%93%E7%94%A8-%E5%85%A8%E7%BD%91vip%E8%A7%86%E9%A2%91%E5%85%8D%E8%B4%B9%E7%A0%B4%E8%A7%A3%E5%8E%BB%E5%B9%BF%E5%91%8A-%E5%85%A8%E7%BD%91%E9%9F%B3%E4%B9%90%E7%9B%B4%E6%8E%A5%E4%B8%8B%E8%BD%BD-%E7%9F%A5%E4%B9%8E%E5%A2%9E%E5%BC%BA-%E7%9F%AD%E8%A7%86%E9%A2%91%E6%97%A0%E6%B0%B4%E5%8D%B0%E4%B8%8B%E8%BD%BD-%E7%99%BE%E5%BA%A6%E7%BD%91%E7%9B%98%E7%9B%B4%E6%8E%A5%E4%B8%8B%E8%BD%BD%E7%AD%89%E5%A4%9A%E5%8A%9F%E8%83%BD%E5%B7%A5%E5%85%B7%E7%AE%B1-%E5%8A%9F%E8%83%BD%E5%8F%AF%E7%8B%AC%E7%AB%8B%E5%BC%80%E5%85%B3-%E9%95%BF%E6%9C%9F%E6%9B%B4%E6%96%B0-%E6%94%BE%E5%BF%83%E4%BD%BF%E7%94%A8-v5-4">懒人专用</a></td>
</tr>
<tr>
<td style="text-align:center">知乎</td>
<td style="text-align:center">干净整洁的排版, 多功能, 屏蔽盐选</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/419081-%E7%9F%A5%E4%B9%8E%E5%A2%9E%E5%BC%BA">知乎增强</a></td>
</tr>
<tr>
<td style="text-align:center">CSDN</td>
<td style="text-align:center">去广告,优化排版, 最主要的是不用登陆了</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/378351-%E6%8C%81%E7%BB%AD%E6%9B%B4%E6%96%B0-csdn%E5%B9%BF%E5%91%8A%E5%AE%8C%E5%85%A8%E8%BF%87%E6%BB%A4-%E4%BA%BA%E6%80%A7%E5%8C%96%E8%84%9A%E6%9C%AC%E4%BC%98%E5%8C%96-%E4%B8%8D%E7%94%A8%E5%86%8D%E7%99%BB%E5%BD%95%E4%BA%86-%E8%AE%A9%E4%BD%A0%E4%BD%93%E9%AA%8C%E4%BB%A4%E4%BA%BA%E6%83%8A%E5%96%9C%E7%9A%84%E5%B4%AD%E6%96%B0csdn">csdn_不用登陆_广告过滤</a></td>
</tr>
<tr>
<td style="text-align:center">所有</td>
<td style="text-align:center">降低屏幕亮度, 护眼用, 但事实上吧&hellip; 太暗了看起来也会吃力的, 看个人喜好吧, 最一开始的时候觉得还是不错的</td>
<td style="text-align:center"><a href="https://greasyfork.org/zh-CN/scripts/426377-%E6%8A%A4%E7%9C%BC%E6%A8%A1%E5%BC%8F">护眼模式</a></td>
</tr>
<tr>
<td style="text-align:center">超星/智慧树</td>
<td style="text-align:center">网课助手, 懂得都懂, 只是刷题方面有个题库要钱, 但准确度确实高, 建议大招留给考试用</td>
<td style="text-align:center"><a href="https://greasyfork.org/scripts/442075-ocs-%E7%BD%91%E8%AF%BE%E5%8A%A9%E6%89%8B/code/OCS%20%E7%BD%91%E8%AF%BE%E5%8A%A9%E6%89%8B.user.js">OCS 网课助手</a></td>
</tr>
<tr>
<td style="text-align:center">超星网课</td>
<td style="text-align:center">用过确实好, 牛逼之处在于, ta会直接修改原有网页,然后不会让你看到/听到视频, 另外还会自己做题(更新还勤快)</td>
<td style="text-align:center"><a href="https://scriptcat.org/script-show-page/336">超星网课小助手</a></td>
</tr>
<tr>
<td style="text-align:center">万能答题</td>
<td style="text-align:center">万能, 就很强(虽然但是错误率&hellip;)</td>
<td style="text-align:center"><a href="https://scriptcat.org/scripts/code/616/%E3%80%90%E4%B8%87%E8%83%BD%E3%80%91%E5%85%A8%E5%B9%B3%E5%8F%B0%E8%87%AA%E5%8A%A8%E7%AD%94%E9%A2%98%E8%84%9A%E6%9C%AC.user.js">【万能】全平台自动答题脚本</a></td>
</tr>
</tbody>
</table>
<h2 id="油猴脚本">油猴脚本</h2>
<ul>
<li>简介:</li>
</ul>
<blockquote>
<p>Greasemonkey，简称GM，中文俗称为“油猴子”，是Mozilla Firefox的一个附加组件。它让用户安装一些脚本使大部分HTML为主的网页于用户端直接改变得更方便易用。<br>
&ndash;<em>摘自 百度百科</em></p>
</blockquote>
<p><strong>简而言之</strong>, 油猴脚本是一个脚本平台, 可以自行安装多个脚本, 每个脚本可以针对需求改变网页样式.<br>
强力的脚本可以达到意想不到的效果 <del>(例如, 将非会员改为会员)</del><br>
<strong>总之</strong>, 优秀的油猴脚本能为生产生活带来的极大的便利</p>
<ul>
<li>使用介绍:
<ul>
<li>关于安装方法, 这篇<a href="https://segmentfault.com/a/1190000041987224">油猴插件及油猴脚本使用手册（完整版）</a>写的挺周延了, 推荐参考</li>
<li>安装可以通过Chrome的插件商店, 当然度娘直搜也会提供很多crx安装的方式, 本文不赘述</li>
<li>插件安装完成后, 有三种基本方式来安装插件
<ol>
<li>按油猴的标志, &ldquo;获取新脚本&rdquo;, 到<a href="https://www.userscript.zone/">search网站</a>搜索, 在<a href="https://greasyfork.org/">Greasy Fork</a>中安装插件</li>
<li>从其他网站上下载了<code>xxx.user.js</code>一类的脚本文件后, 直接拖动到Chrome窗口, 油猴自动识别安装</li>
<li>&ldquo;添加新脚本&rdquo;$\leftarrow$直接自己写脚本</li>
</ol>
</li>
<li>大多数脚本会应对针对的问题的变化而<strong>更新</strong>, 建议开启定时更新</li>
<li>脚本根据用途的不同会有自定义设置, 按油猴标志可以选择开关脚本的部分功能, 或者禁用/启用脚本</li>
<li>网上搜油猴脚本会有大量推荐, 大多都是优质脚本<br>
当然, 要满足特定的个性化需求, 这些还是不够的</li>
</ul>
</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>和&quot;AC-百度一起使用会出问题,择一使用&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>如果和&quot;知乎增强一起使用会出bug,知乎会无法登陆,建议两者择一(效果其实差不多, 但&quot;知乎增强&quot;的功能开关更全面)&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>L15_ACLLib___2023-02-26</title>
			<link>https://zhydada.github.io/posts/l15_acllib___2023-02-26/</link>
			<pubDate>Sun, 26 Feb 2023 23:26:49 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l15_acllib___2023-02-26/</guid>
			<description>目录 简介 Windows API 程序的入口 可能遇到的问题和实现 简介 ACLLib是一个基于Win32API的函数库, 提供了相对简单的方式来制作Windows程序 实</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E7%AE%80%E4%BB%8B">简介</a></li>
<li><a href="#windows-api">Windows API</a>
<ul>
<li><a href="#%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%85%A5%E5%8F%A3">程序的入口</a></li>
<li><a href="#%E5%8F%AF%E8%83%BD%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98%E5%92%8C%E5%AE%9E%E7%8E%B0">可能遇到的问题和实现</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="简介">简介</h2>
<p><strong>ACLLib</strong>是一个基于Win32API的函数库, 提供了<em>相对简单</em>的方式来制作<em><strong>Windows</strong></em>程序<br>
实际提供了<code>.c</code>和<code>.h</code>两个文件</p>
<h2 id="windows-api">Windows API</h2>
<p><strong>API</strong> (Application Programming Interface)中文名是 <strong>应用程序编程接口</strong><br>
因为当第一个32位的 <em><strong>Windows</strong></em> 出现就有了API, 因此也叫做 <em><strong>Win32API</strong></em></p>
<blockquote>
<p>即便Windows发生了天翻地覆的变化, 其核心机制仍旧不变</p>
</blockquote>
<p>这个库由纯C语言编写, 一些早期的Windows程序就是由ta写就</p>
<h3 id="程序的入口">程序的入口</h3>
<p>为什么平日里我们要将<code>main</code>作为程序的入口?<br>
这并非是C语言本身所要求的, 而是编译器决定的</p>
<blockquote>
<p>当启动程序的时候, 由操作系统将可执行程序装载到内存中<br>
启动运行, 运行的第一条指令是<strong>启动代码</strong><br>
这个 <strong>启动代码</strong> 是编译器创建的<br>
作用就是去寻找<code>main</code></p>
</blockquote>
<p>对于<em><strong>Win32API</strong></em>来说, 启动代码的<strong>入口函数</strong>是<code>WinMain()</code></p>
<h3 id="可能遇到的问题和实现">可能遇到的问题和实现</h3>
<table>
<thead>
<tr>
<th style="text-align:left">问题</th>
<th style="text-align:left">答案</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">如何产生窗口</td>
<td style="text-align:left">填写一个窗口的结构, 然后注册</td>
</tr>
<tr>
<td style="text-align:left">如何绘制图像</td>
<td style="text-align:left">运用DC(Device Context)设备上下文</td>
</tr>
<tr>
<td style="text-align:left">如何获取用户的鼠标和键盘动作</td>
<td style="text-align:left">消息循环 和 消息处理代码</td>
</tr>
<tr>
<td style="text-align:left">如何绘制标准界面</td>
<td style="text-align:left">无法做到(极为复杂)</td>
</tr>
</tbody>
</table>
]]></content>
		</item>
		
		<item>
			<title>Part2_字符串___2023-02-23</title>
			<link>https://zhydada.github.io/posts/part2_%E5%AD%97%E7%AC%A6%E4%B8%B2___2023-02-23/</link>
			<pubDate>Thu, 23 Feb 2023 14:42:43 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/part2_%E5%AD%97%E7%AC%A6%E4%B8%B2___2023-02-23/</guid>
			<description>目录 字符串 标识字符串 字符串的使用 使用说明 列出模块中的函数 函数说明 打印文档字符串 字符串 标识字符串 有三种方式: 单引号: a=&#39;She said&amp;quot;Yes!&amp;quot;&#39; 字符串的内容中允许有双</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2">字符串</a>
<ul>
<li><a href="#%E6%A0%87%E8%AF%86%E5%AD%97%E7%AC%A6%E4%B8%B2">标识字符串</a></li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E4%BD%BF%E7%94%A8">字符串的使用</a></li>
</ul>
</li>
<li><a href="#%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E">使用说明</a>
<ul>
<li><a href="#%E5%88%97%E5%87%BA%E6%A8%A1%E5%9D%97%E4%B8%AD%E7%9A%84%E5%87%BD%E6%95%B0">列出模块中的函数</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E">函数说明</a></li>
<li><a href="#%E6%89%93%E5%8D%B0%E6%96%87%E6%A1%A3%E5%AD%97%E7%AC%A6%E4%B8%B2">打印文档字符串</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="字符串">字符串</h2>
<h3 id="标识字符串">标识字符串</h3>
<p>有三种方式:</p>
<ul>
<li>单引号:
<ul>
<li><code>a='She said&quot;Yes!&quot;'</code></li>
<li>字符串的内容中允许有双引号</li>
</ul>
</li>
<li>双引号:
<ul>
<li><code>b=&quot;I'm fine.&quot;</code></li>
<li>字符串的内容中允许有单引号</li>
</ul>
</li>
<li>三引号:
<ul>
<li>
<pre tabindex="0"><code>c=&#34;&#34;&#34;
There&#39;re some &#34;words&#34;
in these two lines.
&#34;&#34;&#34;
</code></pre></li>
<li>字符串的内容中允许有单/双引号, 也会保留多行内容</li>
</ul>
</li>
</ul>
<blockquote>
<p>单独的三引号是文档注释</p>
</blockquote>
<h3 id="字符串的使用">字符串的使用</h3>
<p>非常灵活, 非常人性化
以下是一些例子</p>
<pre tabindex="0"><code>&gt;&gt;&gt; &#34;ha&#34;*5+&#34;!&#34;*3
&#39;hahahahaha!!!&#39;
</code></pre><h2 id="使用说明">使用说明</h2>
<h3 id="列出模块中的函数">列出模块中的函数</h3>
<p><code>dir(m)</code>可以以数组形式, 列出改模块中所有的函数名</p>
<pre tabindex="0"><code>&gt;&gt;&gt; import math
&gt;&gt;&gt; dir(math)
[&#39;__doc__&#39;, &#39;__loader__&#39;, &#39;__name__&#39;, &#39;__package__&#39;, &#39;__spec__&#39;, &#39;acos&#39;, &#39;acosh&#39;, &#39;asin&#39;, &#39;asinh&#39;, &#39;atan&#39;, &#39;atan2&#39;, &#39;atanh&#39;, &#39;ceil&#39;, &#39;comb&#39;, &#39;copysign&#39;, &#39;cos&#39;, &#39;cosh&#39;, &#39;degrees&#39;, &#39;dist&#39;, &#39;e&#39;, &#39;erf&#39;, &#39;erfc&#39;, &#39;exp&#39;, &#39;expm1&#39;, &#39;fabs&#39;, &#39;factorial&#39;, &#39;floor&#39;, &#39;fmod&#39;, &#39;frexp&#39;, &#39;fsum&#39;, &#39;gamma&#39;, &#39;gcd&#39;, &#39;hypot&#39;, &#39;inf&#39;, &#39;isclose&#39;, &#39;isfinite&#39;, &#39;isinf&#39;, &#39;isnan&#39;, &#39;isqrt&#39;, &#39;lcm&#39;, &#39;ldexp&#39;, &#39;lgamma&#39;, &#39;log&#39;, &#39;log10&#39;, &#39;log1p&#39;, &#39;log2&#39;, &#39;modf&#39;, &#39;nan&#39;, &#39;nextafter&#39;, &#39;perm&#39;, &#39;pi&#39;, &#39;pow&#39;, &#39;prod&#39;, &#39;radians&#39;, &#39;remainder&#39;, &#39;sin&#39;, &#39;sinh&#39;, &#39;sqrt&#39;, &#39;tan&#39;, &#39;tanh&#39;, &#39;tau&#39;, &#39;trunc&#39;, &#39;ulp&#39;]
</code></pre><blockquote>
<p><code>&gt;&gt;&gt; dir(__builtins__)</code>会展示所有 <strong>内置函数</strong></p>
</blockquote>
<blockquote>
<p>带有双下划线的内容一般用于较为复杂的编程, 可以先忽略</p>
</blockquote>
<h3 id="函数说明">函数说明</h3>
<p><code>help(function)</code>打印出改函数的使用说明</p>
<h3 id="打印文档字符串">打印文档字符串</h3>
<p><code>print(fucntion.__doc__)</code></p>
<pre tabindex="0"><code>&gt;&gt;&gt; print(sin.__doc__)
Return the sine of x (measured in radians).
</code></pre>]]></content>
		</item>
		
		<item>
			<title>Part0_学校上课___2023-02-23</title>
			<link>https://zhydada.github.io/posts/part0_%E5%AD%A6%E6%A0%A1%E4%B8%8A%E8%AF%BE___2023-02-23/</link>
			<pubDate>Thu, 23 Feb 2023 14:04:52 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/part0_%E5%AD%A6%E6%A0%A1%E4%B8%8A%E8%AF%BE___2023-02-23/</guid>
			<description>目录 type 整数 浮点数 数组 字符串 复数 取地址 函数 type type(x)返回x的类型 一共有 五大序列 整数 &amp;gt;&amp;gt;&amp;gt; x=1 &amp;gt;&amp;gt;&amp;gt; type(x) &amp;lt;class &amp;#39;int&amp;#39;&amp;gt; 浮点数 &amp;gt;&amp;gt;&amp;gt; x=.5 &amp;gt;&amp;gt;&amp;gt; type(x) &amp;lt;class &amp;#39;float&amp;#39;&amp;gt; 数组 &amp;gt;&amp;gt;&amp;gt; x=[1,2,3] &amp;gt;&amp;gt;&amp;gt; type(x) &amp;lt;class &amp;#39;list&amp;#39;&amp;gt; 字符串 &amp;gt;&amp;gt;&amp;gt;</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#type">type</a>
<ul>
<li><a href="#%E6%95%B4%E6%95%B0">整数</a></li>
<li><a href="#%E6%B5%AE%E7%82%B9%E6%95%B0">浮点数</a></li>
<li><a href="#%E6%95%B0%E7%BB%84">数组</a></li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2">字符串</a></li>
<li><a href="#%E5%A4%8D%E6%95%B0">复数</a></li>
</ul>
</li>
<li><a href="#%E5%8F%96%E5%9C%B0%E5%9D%80">取地址</a></li>
<li><a href="#%E5%87%BD%E6%95%B0">函数</a></li>
</ul>
<hr>
<h2 id="type">type</h2>
<p><code>type(x)</code>返回<code>x</code>的类型
一共有 <strong>五大序列</strong></p>
<h3 id="整数">整数</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; x=1
&gt;&gt;&gt; type(x)
&lt;class &#39;int&#39;&gt;
</code></pre><h3 id="浮点数">浮点数</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; x=.5
&gt;&gt;&gt; type(x)
&lt;class &#39;float&#39;&gt;
</code></pre><h3 id="数组">数组</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; x=[1,2,3]
&gt;&gt;&gt; type(x)
&lt;class &#39;list&#39;&gt;
</code></pre><h3 id="字符串">字符串</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; x=&#39;&#39;&#39;Tom said,\n &#34;Let&#39;s go!&#34;&#39;&#39;&#39;
&gt;&gt;&gt; x
&#39;Tom said,\n &#34;Let\&#39;s go!&#34;&#39;
&gt;&gt;&gt; print(x)
Tom said,
 &#34;Let&#39;s go!&#34;
&gt;&gt;&gt; type(x)
&lt;class &#39;str&#39;&gt;
</code></pre><h3 id="复数">复数</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; 1j*1j
(-1+0j)
</code></pre><h2 id="取地址">取地址</h2>
<p><code>id(x)</code>返回一个代表地址的整数</p>
<blockquote>
<p><strong>注意</strong>, 修改变量的值地址也会改变</p>
</blockquote>
<h2 id="函数">函数</h2>
<p><code>ord(x)</code>获得ASCII码<br>
<code>dir(import)</code>列出库中对象<br>
<code>help(fun)</code>获得函数的说明</p>
]]></content>
		</item>
		
		<item>
			<title>Part1_运算___2023-02-23</title>
			<link>https://zhydada.github.io/posts/part1_%E8%BF%90%E7%AE%97___2023-02-23/</link>
			<pubDate>Thu, 23 Feb 2023 13:35:33 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/part1_%E8%BF%90%E7%AE%97___2023-02-23/</guid>
			<description>目录 运算 整数运算 浮点运算 溢出 精度问题 复数 数学函数 常用的数学函数 导入库 类型转换 显式转换 隐式转换 运算 整数运算 符号 含义 举例 + 加法 &amp;gt;&amp;gt;&amp;gt;1+2 3 - 减法 &amp;gt;&amp;gt;&amp;gt;3-2 1 * 乘</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E8%BF%90%E7%AE%97">运算</a>
<ul>
<li><a href="#%E6%95%B4%E6%95%B0%E8%BF%90%E7%AE%97">整数运算</a></li>
<li><a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97">浮点运算</a>
<ul>
<li><a href="#%E6%BA%A2%E5%87%BA">溢出</a></li>
<li><a href="#%E7%B2%BE%E5%BA%A6%E9%97%AE%E9%A2%98">精度问题</a></li>
</ul>
</li>
<li><a href="#%E5%A4%8D%E6%95%B0">复数</a></li>
<li><a href="#%E6%95%B0%E5%AD%A6%E5%87%BD%E6%95%B0">数学函数</a>
<ul>
<li><a href="#%E5%B8%B8%E7%94%A8%E7%9A%84%E6%95%B0%E5%AD%A6%E5%87%BD%E6%95%B0">常用的数学函数</a></li>
<li><a href="#%E5%AF%BC%E5%85%A5%E5%BA%93">导入库</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">类型转换</a>
<ul>
<li><a href="#%E6%98%BE%E5%BC%8F%E8%BD%AC%E6%8D%A2">显式转换</a></li>
<li><a href="#%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2">隐式转换</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="运算">运算</h2>
<h3 id="整数运算">整数运算</h3>
<table>
<thead>
<tr>
<th style="text-align:center">符号</th>
<th style="text-align:center">含义</th>
<th style="text-align:center">举例</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>+</code></td>
<td style="text-align:center">加法</td>
<td style="text-align:center"><code>&gt;&gt;&gt;1+2</code><br><code>3</code></td>
</tr>
<tr>
<td style="text-align:center"><code>-</code></td>
<td style="text-align:center">减法</td>
<td style="text-align:center"><code>&gt;&gt;&gt;3-2</code><br><code>1</code></td>
</tr>
<tr>
<td style="text-align:center"><code>*</code></td>
<td style="text-align:center">乘法</td>
<td style="text-align:center"><code>&gt;&gt;&gt;2*3</code><br><code>6</code></td>
</tr>
<tr>
<td style="text-align:center"><code>/</code></td>
<td style="text-align:center">除法</td>
<td style="text-align:center"><code>&gt;&gt;&gt;22/7</code><br><code>3.142857142857143</code></td>
</tr>
<tr>
<td style="text-align:center"><code>**</code></td>
<td style="text-align:center">乘方</td>
<td style="text-align:center"><code>&gt;&gt;&gt;2**3</code><br><code>8</code></td>
</tr>
<tr>
<td style="text-align:center"><code>%</code></td>
<td style="text-align:center">求余</td>
<td style="text-align:center"><code>&gt;&gt;&gt;25%4</code><br><code>1</code></td>
</tr>
<tr>
<td style="text-align:center"><code>//</code></td>
<td style="text-align:center">整除(向下取整)</td>
<td style="text-align:center"><code>&gt;&gt;&gt;25//4</code><br><code>6</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p>python对于整数的长度不设限制</p>
</blockquote>
<h3 id="浮点运算">浮点运算</h3>
<p><strong>浮点数</strong>是指带有小数点的数字, 浮点数参与的运算就是<strong>浮点运算</strong><br>
所有整数运算符<strong>都适用于</strong>浮点运算</p>
<p>小数的写法非常灵活:</p>
<ul>
<li><code>&gt;&gt;&gt;3.</code><br>
<code>3.0</code></li>
<li><code>&gt;&gt;&gt;.5</code><br>
<code>0.5</code></li>
<li><code>&gt;&gt;&gt;2.3e02</code><br>
<code>230.0</code></li>
</ul>
<blockquote>
<p><strong>注意</strong>:  <code>5</code>和<code>5.0</code>完全不一样<br>
前者是<em>整数</em>, 后者是<em>浮点数</em><br>
其内部表示大相径庭</p>
</blockquote>
<h4 id="溢出">溢出</h4>
<p>浮点数<strong>存在上下限</strong>, 超出会导致<em>溢出错误</em></p>
<pre tabindex="0"><code>&gt;&gt;&gt; 500.0**99999
Traceback (most recent call last):
  File &#34;&lt;pyshell#18&gt;&#34;, line 1, in &lt;module&gt;
    500.0**99999
OverflowError: (34, &#39;Result too large&#39;)
</code></pre><blockquote>
<p><strong>注意</strong>: python有可能会对这类错误沉默不语<br>
溢出产生的错误由程序员自己承担</p>
</blockquote>
<h4 id="精度问题">精度问题</h4>
<p>浮点数 <strong>精度有限</strong></p>
<pre tabindex="0"><code>&gt;&gt;&gt; 1-2/3
0.33333333333333337
</code></pre><blockquote>
<p>细微错误的不断累积可能导致灾难</p>
</blockquote>
<h3 id="复数">复数</h3>
<p>很少涉及</p>
<pre tabindex="0"><code>&gt;&gt;&gt; 1j*1j
(-1+0j)
</code></pre><h3 id="数学函数">数学函数</h3>
<h4 id="常用的数学函数">常用的数学函数</h4>
<table>
<thead>
<tr>
<th style="text-align:center">函数</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>ceil(x)</code></td>
<td style="text-align:center">向上取整</td>
</tr>
<tr>
<td style="text-align:center"><code>cos(x)</code></td>
<td style="text-align:center">余弦</td>
</tr>
<tr>
<td style="text-align:center"><code>degress(x)</code></td>
<td style="text-align:center">弧度制转换为度数</td>
</tr>
<tr>
<td style="text-align:center"><code>exp(x)</code></td>
<td style="text-align:center"><code>e</code>的<code>x</code>次方</td>
</tr>
<tr>
<td style="text-align:center"><code>factorial(x)</code></td>
<td style="text-align:center">阶乘(<code>x</code>必须是整数)</td>
</tr>
<tr>
<td style="text-align:center"><code>log(x)</code></td>
<td style="text-align:center">自然对数</td>
</tr>
<tr>
<td style="text-align:center"><code>log(x,b)</code></td>
<td style="text-align:center"><code>b</code>为底数的对数</td>
</tr>
<tr>
<td style="text-align:center"><code>pow(x,y)</code></td>
<td style="text-align:center"><code>x</code>的<code>y</code>次方</td>
</tr>
<tr>
<td style="text-align:center"><code>radians(x)</code></td>
<td style="text-align:center">度数转换为弧度制</td>
</tr>
<tr>
<td style="text-align:center"><code>sin(x)</code></td>
<td style="text-align:center">正弦</td>
</tr>
<tr>
<td style="text-align:center"><code>sqrt(x)</code></td>
<td style="text-align:center">开平方根</td>
</tr>
<tr>
<td style="text-align:center"><code>tan(x)</code></td>
<td style="text-align:center">正切</td>
</tr>
</tbody>
</table>
<h4 id="导入库">导入库</h4>
<p>方法一:<br>
<code>&gt;&gt;&gt; import math</code><br>
要使用<code>math</code>库的函数, 需要在函数名前面放上<code>math.</code></p>
<p>方法二:<br>
<code>&gt;&gt;&gt; from math import *</code>
这样在调用的时候就不需要在函数名前面加上<code>math.</code>了</p>
<blockquote>
<p>方法一比较安全, 不会和已有的函数名冲突</p>
</blockquote>
<blockquote>
<p>方法二还可以只导入特定的函数, 如:<br>
<code>&gt;&gt;&gt; from math import sin, cos, tan</code></p>
</blockquote>
<h2 id="类型转换">类型转换</h2>
<h3 id="显式转换">显式转换</h3>
<pre tabindex="0"><code>&gt;&gt;&gt; int(2.6)
2
&gt;&gt;&gt; float(3)
3.0
&gt;&gt;&gt; str(85.6)
&#39;85.6&#39;
</code></pre><h3 id="隐式转换">隐式转换</h3>
]]></content>
		</item>
		
		<item>
			<title>L13_可变数组与链表___2023-02-14</title>
			<link>https://zhydada.github.io/posts/l14_%E5%8F%AF%E5%8F%98%E6%95%B0%E7%BB%84%E4%B8%8E%E9%93%BE%E8%A1%A8___2023-02-14/</link>
			<pubDate>Tue, 14 Feb 2023 22:18:53 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l14_%E5%8F%AF%E5%8F%98%E6%95%B0%E7%BB%84%E4%B8%8E%E9%93%BE%E8%A1%A8___2023-02-14/</guid>
			<description>目录 可变数组 思路 实现 定义结构 创建数组 释放数组 数组大小 获得指定单元的地址 数组的增长 链表 概述 实现思路 程序实现 定义节点的结构体 增加一个节点到链表末</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%8F%AF%E5%8F%98%E6%95%B0%E7%BB%84">可变数组</a>
<ul>
<li><a href="#%E6%80%9D%E8%B7%AF">思路</a></li>
<li><a href="#%E5%AE%9E%E7%8E%B0">实现</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E7%BB%93%E6%9E%84">定义结构</a></li>
<li><a href="#%E5%88%9B%E5%BB%BA%E6%95%B0%E7%BB%84">创建数组</a></li>
<li><a href="#%E9%87%8A%E6%94%BE%E6%95%B0%E7%BB%84">释放数组</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E5%A4%A7%E5%B0%8F">数组大小</a></li>
<li><a href="#%E8%8E%B7%E5%BE%97%E6%8C%87%E5%AE%9A%E5%8D%95%E5%85%83%E7%9A%84%E5%9C%B0%E5%9D%80">获得指定单元的地址</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E5%A2%9E%E9%95%BF">数组的增长</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E9%93%BE%E8%A1%A8">链表</a>
<ul>
<li><a href="#%E6%A6%82%E8%BF%B0">概述</a></li>
<li><a href="#%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF">实现思路</a></li>
<li><a href="#%E7%A8%8B%E5%BA%8F%E5%AE%9E%E7%8E%B0">程序实现</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E8%8A%82%E7%82%B9%E7%9A%84%E7%BB%93%E6%9E%84%E4%BD%93">定义节点的结构体</a></li>
<li><a href="#%E5%A2%9E%E5%8A%A0%E4%B8%80%E4%B8%AA%E8%8A%82%E7%82%B9%E5%88%B0%E9%93%BE%E8%A1%A8%E6%9C%AB%E5%B0%BE">增加一个节点到链表末尾</a></li>
<li><a href="#%E9%93%BE%E8%A1%A8%E7%9A%84%E9%81%8D%E5%8E%86">链表的遍历</a></li>
<li><a href="#%E9%93%BE%E8%A1%A8%E7%9A%84%E6%A3%80%E7%B4%A2%E4%B8%8E%E5%88%A0%E9%99%A4">链表的检索与删除</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="可变数组">可变数组</h2>
<h3 id="思路">思路</h3>
<p>C语言中, 数组被一旦定义就<strong>无法改变其大小</strong><br>
如果想得到一个&quot;可变数组&quot;, 应当有一下特点:</p>
<ul>
<li>可以增长</li>
<li>要能知道当前数组确切的大小</li>
<li>要有方便合理的方法访问到其中的单元</li>
</ul>
<p>考虑创建一系列实现特定功能的函数库:</p>
<ul>
<li>创建这样的数组: <code>Array array_create(int init_size);</code></li>
<li>释放数组: <code>void array_free(Array *a);</code></li>
<li>获得数组大小: <code>int array_size(const Array *a);</code></li>
<li>获得指定单元的地址: <code>int* array_at(Array *a, int index);</code></li>
<li>扩大数组的空间: <code>void array_inflate(Array *a, int more_size);</code></li>
</ul>
<h3 id="实现">实现</h3>
<h4 id="定义结构">定义结构</h4>
<pre tabindex="0"><code>typedef struct {
    int *array;
    int size;
} Array;
</code></pre><blockquote>
<p>其实, 可以直接定义<code>*Array</code>指针, 原因是函数调用基本都要求传指针, 直接定义为指针会显得方便美观<br>
但是, ta有两个严重的弊端<br>
首先, 阅读代码的人, 很难察觉这是一个指针<br>
其次, 无法在局部范围内, 定义出一个<code>Array</code></p>
<p>因此, 还是老老实实的定义本体</p>
</blockquote>
<h4 id="创建数组">创建数组</h4>
<pre tabindex="0"><code>Array array_create(int init_size)
{
    Array a;
    a.size = init_size;
    a.array = (int *)malloc(sizeof(int) * a.size);
    return a;
}
</code></pre><h4 id="释放数组">释放数组</h4>
<pre tabindex="0"><code>void array_free(Array *a){
    free(a-&gt;array);
    a-&gt;array = NULL;
    a-&gt;size = 0;
}
</code></pre><blockquote>
<p>后面两行是出于保险起见</p>
</blockquote>
<h4 id="数组大小">数组大小</h4>
<pre tabindex="0"><code>int array_size(const Array *a){
    return a-&gt;size;
}
</code></pre><blockquote>
<p>为什么如此简单的事情还要额外创造一个函数?<br>
这个做法有个专门的称呼: <strong>封装</strong><br>
封装函数<strong>极为有用</strong>, 为后期的修改提供了可能<br>
例如, 如果后来开发中, 要得到size必须先通过一段保护程序<br>
那么就可以在这个封装函数中修改<br>
而且外部不知道具体如何实现, 对size形成了保护<br>
而如果每次都采用直接调用, 那么要耗费大量精力做修改, 这是很划不来的</p>
</blockquote>
<h4 id="获得指定单元的地址">获得指定单元的地址</h4>
<pre tabindex="0"><code>int *array_at(Array *a, int index){
    return &amp;(a-&gt;array[index]);
}
</code></pre><blockquote>
<p>为什么要的是指针?<br>
因为这样可以 <strong>访问</strong> 这个元素<br>
这意味着既能读取又能写入</p>
</blockquote>
<blockquote>
<p>考虑到在函数前加星号<code>*</code>可能会引起不适<br>
可以再添加一对函数(名字可以是read和set), 来实现同样的功能<br>
这么做繁琐, 但是增强了可读性, 当然, 直接获取指针其实也还行</p>
</blockquote>
<h4 id="数组的增长">数组的增长</h4>
<p>简要来说, 就是: 申请一块新的, 把旧的释放掉</p>
<pre tabindex="0"><code>void array_inflate(Array *a, int more_size)
{
    int *p = (int *)malloc(sizeof(int) * (a-&gt;size + more_size));
    int i;
    for (i = 0; i &lt; a-&gt;size; i++)
    {
        p[i] = a-&gt;array[i];
    }
    free(a-&gt;array);
    a-&gt;array = p;
    a-&gt;size += more_size;
}
</code></pre><p>什么时候要增长数组呢?<br>
当我们访问一个元素的时候, 发现下标超出了数组的大小, 就意味着数组不够用了<br>
因此改进<em><strong>array_at</strong></em>方法:</p>
<pre tabindex="0"><code>int *array_at(Array *a, int index)
{
    if(index&gt;=a-&gt;size){
        array_inflate(a, ((index / BLOCK_SIZE) + 1) * BLOCK_SIZE - a-&gt;size);
    }
    return &amp;(a-&gt;array[index]);
}
</code></pre><blockquote>
<p>为什么有<em><strong>BLOCK_SIZE</strong></em>?<br>
设想我们的数组撑满了, 此时需要再往里填一些数(比如在读入数据的时候)<br>
那么如果增长的大小为<code>index - a-&gt;size</code><br>
即便只是读入一个数句, 就要调用一次<em><strong>array_inflate</strong></em>函数<br>
要知道, 这意味着数组重新复制一遍, 无异于大动干戈</p>
<p>因此最好的做法是一次增长 <strong>&ldquo;一块&quot;空间</strong><br>
比如说一次就增长<code>5</code>的倍数大小的空间<br>
这样做最经济高效</p>
</blockquote>
<p>为此, 我们还要在文件的前面添上常量声明:</p>
<pre tabindex="0"><code>const BLOCK_SIZE = 5;
</code></pre><blockquote>
<p>如何理解 <code>((index / BLOCK_SIZE) + 1) * BLOCK_SIZE</code>呢?<br>
其实就是向上取整<br>
如果index是<code>2</code>, 那么就是<code>5</code><br>
如果index是<code>67</code>, 那么就是<code>70</code><br>
保证数组的大小总是<em><strong>BLOCK_SIZE</strong></em>的整数倍</p>
</blockquote>
<h2 id="链表">链表</h2>
<h3 id="概述">概述</h3>
<blockquote>
<p>自动增长的数组是一个很有用的工具<br>
但是, ta最大的<strong>缺点</strong>在于: 每次都要申请一个能容纳全部元素的新的空间<br>
这会导致两个问题:</p>
<blockquote>
<p>拷贝一次要<strong>花很多时间</strong></p>
</blockquote>
<blockquote>
<p>当数组中的总数据量比可用空间的<strong>一半要多</strong>的时候, 明明可以容纳下, 但没法再申请空间了</p>
</blockquote>
</blockquote>
<p><strong>链表</strong>, 就是不再拷贝数组, 当数组不够用的时候, 开辟一块新的空间, 并用一个指针将两者&quot;链接&quot;起来<br>
这么做不但在<strong>时间上高效</strong>, 而且还能充分利用到可用空间的角角落落, <strong>空间使用上也高效</strong></p>
<h3 id="实现思路">实现思路</h3>
<p>每一个储存单元包含一个 <em><strong>int</strong></em> 数组和一个 <em><strong>int</strong></em> 指针<br>
其中:</p>
<ul>
<li>第一个储存单元要能表示自己是第一个, 要有个head标志</li>
<li>中间每个指针都指向下一个单元的地址</li>
<li>最后一个指针也要有个表示, 表明自己是最后的末尾</li>
</ul>
<p>这样的每个单元被称为 <strong>节点</strong>(<em>node</em>), 整个这一系列的节点被称为 <strong>链表</strong>(<em>linked list</em>)<br>
当我们要读入 <strong>未知数量的</strong> 数据时, 应当有下列的行为:</p>
<ul>
<li>先<code>Node *head = NULL</code>定义一个<strong>头部节点</strong>, 代表着有这么一个链表存在</li>
<li>当有数据进入时申请空间, 创建一个新的<code>Node</code></li>
<li>把数据导入这个节点的<code>value</code>中, 并将<code>*next</code>指针设定为<em><strong>NULL</strong></em>(因为新节点添加在链表的末尾, 因此用指针指向<em><strong>NULL</strong></em>表示)</li>
<li>找到链表的最后一个节点
<ul>
<li>先定义一个<code>Node *last</code>指针, 让ta的初始指向为<code>*head</code>一致
<blockquote>
<p>这里还需要判断一下, <code>*last</code>是不是就是<code>*head</code></p>
</blockquote>
</li>
<li>看<code>*last</code>指针指向的<code>Node</code>对应的<code>*next</code>是不是<em><strong>NULL</strong></em></li>
<li>不是的话用循环继续找下去</li>
<li>是的话, 就说明此时这个<code>*last</code>指向的就是最后的节点了</li>
</ul>
</li>
<li>把最后的节点的<code>*next</code>改成 现在新添加的这个<code>Node</code>的地址, 即, 实现了 <strong>链接</strong></li>
</ul>
<h3 id="程序实现">程序实现</h3>
<h4 id="定义节点的结构体">定义节点的结构体</h4>
<pre tabindex="0"><code>typedef struct _node{
    int value;
    struct _node *next;
} Node;
</code></pre><blockquote>
<p>注意一个细节, 观察<strong>下面这段错误代码</strong>和上面的正确的代码的区别:</p>
<pre tabindex="0"><code>typedef struct _node{
    int value;
    Node *next;
} Node;
</code></pre><p>区别在于定义结构指针的时候用<code>_node</code>还是声明好的结构<code>Node</code><br>
注意, 编译器在第三行声明成员变量的名称时, 还 <strong>&ldquo;不认识&rdquo;</strong> <code>Node</code>是什么<br>
但如果改写成<code>struct _node</code>, 编译器是知道的<br>
<strong>在那之后</strong>再将<code>struct _node</code>定义成<code>Node</code>(两者等价)</p>
<blockquote>
<p>P.S.这个做法很常见</p>
</blockquote>
</blockquote>
<h4 id="增加一个节点到链表末尾">增加一个节点到链表末尾</h4>
<p>把方才实现思路中, **&ldquo;添加一个新节点到链表最末尾&rdquo;**这个功能抽离封装为函数</p>
<pre tabindex="0"><code>void add(Node *head, int number)
{
    Node *p = (Node *)malloc(sizeof(Node));
    p-&gt;value = number;
    p-&gt;next = NULL;
    Node *last = head;
    if (last)
    {
        while (last-&gt;next)
        {
            last = last-&gt;next;
        }
        last-&gt;next = p;
    }
    else
    {
        head = p;
    }
}
</code></pre><p>但这个粗糙的函数有个问题, 那就是<code>head = p</code>这处要求改变传入的<code>head</code>, 而由于在函数中, 因此不奏效<br>
有多种方法可以解决:</p>
<ol>
<li>用全局变量</li>
<li>用 <strong>return</strong> 返回一个<code>head</code></li>
<li>传入一个<code>head</code>的地址(指针的指针)</li>
<li>自定义一个新的结构, 这个结构中包含的成员变量是<code>Node</code>的指针</li>
</ol>
<p>前几种容易考虑到, 着重分析一下第4个方法:<br>
先要额外定义一个结构<code>_List</code></p>
<pre tabindex="0"><code>typedef struct _List{
    Node *head;
} List;
</code></pre><p>接着修改函数, 传入一个<code>List</code>的指针<code>List *pList</code>以修改函数外的变量<br>
再将<code>head</code>改成<code>pList-&gt;head</code>, 得到最终的版本:</p>
<pre tabindex="0"><code>void add(List *pList, int number)
{
    Node *p = (Node *)malloc(sizeof(Node));
    p-&gt;value = number;
    p-&gt;next = NULL;
    Node *last = pList-&gt;head;
    if (last)
    {
        while (last-&gt;next)
        {
            last = last-&gt;next;
        }
        last-&gt;next = p;
    }
    else
    {
        pList-&gt;head = p;
    }
}
</code></pre><blockquote>
<p>为什么要这么做呢?<br>
因为, 用一个自己定义的<code>List</code>结构来容纳<code>head</code>这个node的<strong>指针</strong><br>
在阅读上更容易接受, 节点不再单独出现, 更有链表的样貌<br>
此外, 这么做还能允许后期加入<strong>更多的功能</strong></p>
<p>例如, 为了寻找链表的尾巴, 每次都需要做一个循环<br>
那么就可以在这个<code>List</code>结构中加入<code>Node *last</code><br>
每次添加新的<code>Node</code>之后更新<code>last</code>, 高效且易懂</p>
</blockquote>
<h4 id="链表的遍历">链表的遍历</h4>
<p>用一个循环搞定</p>
<pre tabindex="0"><code>Node *p;
for (p = list.head; p; p=p-&gt;next)
{
    printf(&#34;%d\t&#34;, p-&gt;value);
}
</code></pre><p>封装为函数:</p>
<pre tabindex="0"><code>void pirnt(List *pList)
{
    Node *p;
    for (p = pList-&gt;head; p; p = p-&gt;next)
    {
        printf(&#34;%d\t&#34;, p-&gt;value);
    }
    printf(&#34;\n&#34;);
}
</code></pre><h4 id="链表的检索与删除">链表的检索与删除</h4>
<p>检索就是在遍历的过程中比较<code>value</code>和目标值<br>
实现删除有如下步骤:</p>
<ul>
<li>把前面<code>Node</code>的指针指向后面的<code>Node</code></li>
<li><em><strong>free</strong></em>当前的<code>Node</code></li>
</ul>
<p>问题在于, 无法获知 <strong>上一个<code>Node</code></strong><br>
考虑再加一个指针, 记录上一个<code>Node</code></p>
<pre tabindex="0"><code>void delet(List *pList, int number)
{
    Node *p, *q;
    for (q = NULL, p = pList-&gt;head; p; q = p, p = p-&gt;next)
    {
        if (p-&gt;value == number)
        {
            if (q)
            {
                q-&gt;next = p-&gt;next;
            }else{
                pList-&gt;head = p-&gt;next;
            }
            free(p);
            break;
        }
    }
}
</code></pre><blockquote>
<p><strong>一定要检查边界条件</strong>!<br>
任何在<code>-&gt;</code>左侧的指针必须要检查是否为<em><strong>NULL</strong></em></p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>L13_位运算___2023-02-11</title>
			<link>https://zhydada.github.io/posts/l13_%E4%BD%8D%E8%BF%90%E7%AE%97___2023-02-11/</link>
			<pubDate>Sat, 11 Feb 2023 22:44:25 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l13_%E4%BD%8D%E8%BF%90%E7%AE%97___2023-02-11/</guid>
			<description>目录 位运算 按位运算 按位取与 按位取或 按位取反 按位异或 与逻辑运算的区别 移位运算 左移 右移 误区 举例&amp;ndash;输出一个数的二进制 实现思路 代码实现 位</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E4%BD%8D%E8%BF%90%E7%AE%97">位运算</a>
<ul>
<li><a href="#%E6%8C%89%E4%BD%8D%E8%BF%90%E7%AE%97">按位运算</a>
<ul>
<li><a href="#%E6%8C%89%E4%BD%8D%E5%8F%96%E4%B8%8E">按位取与</a></li>
<li><a href="#%E6%8C%89%E4%BD%8D%E5%8F%96%E6%88%96">按位取或</a></li>
<li><a href="#%E6%8C%89%E4%BD%8D%E5%8F%96%E5%8F%8D">按位取反</a></li>
<li><a href="#%E6%8C%89%E4%BD%8D%E5%BC%82%E6%88%96">按位异或</a></li>
</ul>
</li>
<li><a href="#%E4%B8%8E%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E7%9A%84%E5%8C%BA%E5%88%AB">与逻辑运算的区别</a></li>
<li><a href="#%E7%A7%BB%E4%BD%8D%E8%BF%90%E7%AE%97">移位运算</a>
<ul>
<li><a href="#%E5%B7%A6%E7%A7%BB">左移</a></li>
<li><a href="#%E5%8F%B3%E7%A7%BB">右移</a></li>
<li><a href="#%E8%AF%AF%E5%8C%BA">误区</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E4%B8%BE%E4%BE%8B--%E8%BE%93%E5%87%BA%E4%B8%80%E4%B8%AA%E6%95%B0%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6">举例&ndash;输出一个数的二进制</a>
<ul>
<li><a href="#%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF">实现思路</a></li>
<li><a href="#%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0">代码实现</a></li>
</ul>
</li>
<li><a href="#%E4%BD%8D%E6%AE%B5">位段</a>
<ul>
<li><a href="#%E8%83%8C%E6%99%AF%E4%BB%8B%E7%BB%8D">背景介绍</a></li>
<li><a href="#%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0-1">代码实现</a></li>
<li><a href="#%E5%88%A9%E7%94%A8%E7%BB%93%E6%9E%84%E4%BD%93%E5%88%9B%E9%80%A0%E4%BD%8D%E6%AE%B5">利用结构体创造位段</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E7%BB%93%E6%9E%84%E4%BD%93">定义一个结构体</a></li>
<li><a href="#%E4%B8%BA%E7%BB%93%E6%9E%84%E4%BD%93%E8%B5%8B%E5%80%BC%E5%B9%B6%E6%9F%A5%E7%9C%8B%E7%BB%93%E6%9E%9C">为结构体赋值并查看结果</a></li>
<li><a href="#%E4%BC%98%E7%BC%BA%E7%82%B9">优缺点</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="位运算">位运算</h2>
<p>C语言中有如下<strong>位运算</strong>的运算符  </p>
<table>
<thead>
<tr>
<th style="text-align:center">运算符</th>
<th style="text-align:center">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>&amp;</code></td>
<td style="text-align:center">按位的与</td>
</tr>
<tr>
<td style="text-align:center"><code>|</code></td>
<td style="text-align:center">按位的或</td>
</tr>
<tr>
<td style="text-align:center"><code>~</code></td>
<td style="text-align:center">按位取反</td>
</tr>
<tr>
<td style="text-align:center"><code>^</code></td>
<td style="text-align:center">按位的异或</td>
</tr>
<tr>
<td style="text-align:center"><code>&lt;&lt;</code></td>
<td style="text-align:center">左移</td>
</tr>
<tr>
<td style="text-align:center"><code>&gt;&gt;</code></td>
<td style="text-align:center">右移</td>
</tr>
</tbody>
</table>
<h3 id="按位运算">按位运算</h3>
<h4 id="按位取与">按位取与</h4>
<p><strong>定义</strong>: 对于第<code>i</code>位, 如果两数都为<code>1</code>, 则与的结果为<code>1</code>, 否则为<code>0</code><br>
<strong>口诀</strong>: 同真则真, 一假则假<br>
<strong>应用</strong>:</p>
<ul>
<li>让某一位为<code>0</code>: 对于<code>x</code>, 要使得其末位为<code>0</code>, 则计算<code>x &amp; 0xFE</code></li>
<li>截取一个数的某一段: 对于一个<code>int x</code>, ta有4个字节, 如果只要最后一个字节的内容, 则计算<code>x &amp; 0xFF</code></li>
</ul>
<h4 id="按位取或">按位取或</h4>
<p><strong>定义</strong>: 对于第<code>i</code>位, 如果两数都为<code>0</code>, 则与的结果为<code>0</code>, 否则为<code>1</code><br>
<strong>口诀</strong>: 一真则真, 同假则假<br>
<strong>应用</strong>:</p>
<ul>
<li>让某一位为<code>1</code>: 对于<code>x</code>, 要使得其末位为<code>1</code>, 则计算<code>x | 0x01</code></li>
<li>拼接两个数: 对于两个一个字节的数<code>0xAB</code>和<code>0xCD</code>, 计算<code>0xAB00 | 0x00CD</code>可以得到拼接的结果<code>0xABCD</code></li>
</ul>
<h4 id="按位取反">按位取反</h4>
<p><strong>定义</strong>: 每个比特的值翻转<br>
<strong>口诀</strong>: 一变零, 零变一<br>
<strong>应用</strong>:</p>
<ul>
<li>让某一位为<code>1</code>: 对于<code>x</code>, 要使得其末位为<code>1</code>, 则计算<code>x | 0x01</code></li>
<li>拼接两个数: 对于两个一个字节的数<code>0xAB</code>和<code>0xCD</code>, 计算<code>0xAB00 | 0x00CD</code>可以得到拼接的结果<code>0xABCD</code></li>
</ul>
<blockquote>
<p><em>补码</em>与<em>取反</em>不同!<br>
补码是在原码取反后<code>+1</code><br>
补码可以看做原码的负数</p>
</blockquote>
<h4 id="按位异或">按位异或</h4>
<p><strong>定义</strong>: 两个位相等则结果为<code>0</code>, 不相等则为<code>1</code><br>
<strong>口诀</strong>: 同则零, 异则一<br>
<strong>应用</strong>:</p>
<ul>
<li>加密: 对一个数用同一个值异或运算两次, 仍得到原来的数<br>
<code>x ^ y ^ y</code> -&gt; <code>x</code></li>
</ul>
<h3 id="与逻辑运算的区别">与逻辑运算的区别</h3>
<p>计算机底层只有<strong>按位运算</strong><br>
所谓<strong>逻辑运算</strong>其实就是将任何非<code>0</code>的数看做<code>1</code>, 然后做按位运算</p>
<table>
<thead>
<tr>
<th style="text-align:center">按位运算</th>
<th style="text-align:center">逻辑运算</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>5 &amp; 4</code> -&gt; <code>4</code></td>
<td style="text-align:center"><code>5 &amp;&amp; 4</code> -&gt; <code>1</code></td>
</tr>
<tr>
<td style="text-align:center"><code>5 | 4</code> -&gt; <code>5</code></td>
<td style="text-align:center"><code>5 || 4</code> -&gt; <code>1</code></td>
</tr>
<tr>
<td style="text-align:center"><code>~4</code> -&gt; <code>3</code></td>
<td style="text-align:center"><code>!4</code> -&gt; <code>0</code></td>
</tr>
</tbody>
</table>
<h3 id="移位运算">移位运算</h3>
<h4 id="左移">左移</h4>
<p><strong>定义</strong>: <code>i &lt;&lt; j</code>将<code>i</code>中所有的位<strong>向左</strong>移动<code>j</code>个位置, 右边填充<code>0</code></p>
<blockquote>
<p>所有小于<em><strong>int</strong></em>的类型, 移位的结果均为<em><strong>int</strong></em><br>
(可能会因为编译器而有不同)</p>
</blockquote>
<blockquote>
<p>注意, 可能会把<em><strong>signed</strong></em>类型的符号位挤掉</p>
</blockquote>
<p><code>x &lt;&lt;= n</code>等价于<code>x *= (int)pow(2.0, n)</code></p>
<h4 id="右移">右移</h4>
<p><strong>定义</strong>: <code>i &gt;&gt; j</code>将<code>i</code>中所有的位<strong>向右</strong>移动<code>j</code>个位置</p>
<ul>
<li>对于<em><strong>unsigned</strong></em>类型, 左边填<code>0</code></li>
<li>对于<em><strong>signed</strong></em>类型, 左边填原来的最高位(即表示符号的那一位)</li>
</ul>
<blockquote>
<p>所有小于<em><strong>int</strong></em>的类型, 移位的结果均为<em><strong>int</strong></em><br>
(可能会因为编译器而有不同)</p>
</blockquote>
<p><code>x &gt;&gt;= n</code>等价于<code>x /= (int)pow(2.0, n)</code></p>
<h4 id="误区">误区</h4>
<p>不要以为<code>x &lt;&lt; -2</code>等价于<code>x &gt;&gt; 2</code>!!!<br>
这个行为未被定义, <strong>会报错</strong></p>
<h2 id="举例--输出一个数的二进制">举例&ndash;输出一个数的二进制</h2>
<h3 id="实现思路">实现思路</h3>
<p>用一个<em><strong>unsigned</strong></em>的mask去查看这个数字每一位是<code>0</code>还是<code>1</code><br>
mask只有一个位上有<code>1</code>, 其余位皆为<code>0</code><br>
那么和要算的数字运算<em>按位取与</em><br>
如果那一位是<code>0</code>, 那么结果是<code>0</code>, 否则就是<code>1</code></p>
<h3 id="代码实现">代码实现</h3>
<pre tabindex="0"><code>void printBin(int number){
    unsigned mask = 1u&lt;&lt;31;
    for (; mask;mask&gt;&gt;=1){
        printf(&#34;%d&#34;, (number &amp; mask) ? 1 : 0);
    }
}
</code></pre><h2 id="位段">位段</h2>
<h3 id="背景介绍">背景介绍</h3>
<blockquote>
<p>在单片机中, 需要给芯片做一些设置<br>
这些设置是通过一个<em>二进制数</em>读入的<br>
为了容易理解, 以下将这个二进制数类比为<em>一连串手势</em><br>
手势的含义在单片机的手册中有明确规定<br>
比如, 规定, 这个二进制数的第3位如果是<code>1</code>, 其含义就是&quot;开启某功能&quot;<br>
这个二进制数的第3位如果是<code>0</code>, 其含义就是&quot;关闭某功能&quot;<br>
当然, 还有可能出现&quot;第4和第5这两个位置上<code>0/1</code><strong>组合出的4种情况</strong>对应某个功能的4个模式&quot;</p>
<p><strong>我们的目标是</strong>, 运用<em>位运算</em>, 将给定的一个二进制数中的某几位, 修改为<code>0</code>或<code>1</code></p>
</blockquote>
<p><strong>题目</strong>: 有一个<em><strong>unsigned</strong></em>二进制数, 要求将从右往左数的第2和第3位比特变成<code>1</code>, 第4位比特变成<code>0</code></p>
<h3 id="代码实现-1">代码实现</h3>
<pre tabindex="0"><code>const unsigned int origin = 0b111000;
unsigned int result = 0b111000;
const unsigned int flag2 = 1u &lt;&lt; 1; //注解1
const unsigned int flag3 = 1u &lt;&lt; 2;
const unsigned int flag4 = 1u &lt;&lt; 3;

result |= flag2 | flag3; //注解2
result &amp;= ~flag4; //注解3

printBin(origin);
printf(&#34;\n&#34;);
printBin(result);
</code></pre><blockquote>
<p><strong>注解1</strong>:<br>
为什么要用<em><strong>const</strong></em>?</p>
<blockquote>
<p>因为这个既然是开关, 那么在后续的程序中修改还会用到<br>
方面后面的使用</p>
</blockquote>
<p>另外还要注意, <code>1u</code>所指就是第一位比特<br>
所以为了对应第二位比特, 只需左移一位</p>
</blockquote>
<blockquote>
<p><strong>注解2</strong>:<br>
这里其实先运算等号右侧的表达式, 其结果是<code>0b110</code><br>
也就是两个开关并在一起</p>
<p>然后<code>|=</code>是一个简写, 就是<em>按位取或</em>之后再赋值<br>
由于只有指定的两个比特是<code>1</code>, 对于其他比特没有变动<br>
而对于指定的两位, 一定变<code>1</code>, 达到效果</p>
</blockquote>
<blockquote>
<p><strong>注解3</strong>:<br>
和上面一样, 不过这一次是先要<em>按位取反</em><br>
这样得到的结果除了指定的位置是<code>0</code>其余都是<code>1</code><br>
运算<em>按位取与</em>, 和<code>1</code>取与结果就是不变<br>
而和<code>0</code>取与必定是<code>0</code>, 同样达到效果</p>
</blockquote>
<h3 id="利用结构体创造位段">利用结构体创造位段</h3>
<blockquote>
<p>考虑到结构体中的成员就是直接排列在一起的<br>
用结构体可以更轻松容易的实现上述效果</p>
</blockquote>
<h4 id="定义一个结构体">定义一个结构体</h4>
<pre tabindex="0"><code>struct U0
{
    unsigned int leading : 3;
    unsigned int FLAG1 : 1;
    unsigned int FLAG2 : 1;
    unsigned int trailing : 27;
};
</code></pre><p>这里冒号<code>:</code>后的数字代表这个成员所占的<strong>比特数</strong><br>
其中:</p>
<ul>
<li><code>leading</code>代表前三个比特, 能表示8种不同的选项</li>
<li><code>FLAG1</code>和<code>FLAG2</code>可能代表两个开关</li>
<li><code>trailing</code>是尾巴的含义, 其作用是为没用到的比特初始化赋值</li>
</ul>
<blockquote>
<p>为什么<code>trailing</code>是<code>27</code>比特呢?<br>
因为总的比特数加起来是<code>32</code>, 刚好是<code>4</code>个字节, 即一个<em><strong>int</strong></em>的大小<br>
一般来说就是一个<em>位段</em>的单元</p>
</blockquote>
<h4 id="为结构体赋值并查看结果">为结构体赋值并查看结果</h4>
<pre tabindex="0"><code>struct U0 uu;
uu.leading = 5;
uu.FLAG1 = 0;
uu.FLAG2 = 1;
uu.trailing = 0;
printBin(*(int *)&amp;uu);
</code></pre><p>这里<code>leading</code>部分可以直接赋十进制的数<br>
因为在内存中都是二进制</p>
<p><strong>注意</strong>输出时的操作: <code>*(int *)&amp;uu</code><br>
<code>uu</code>是一个<strong>结构变量</strong>, 无法直接取出内存中的二进制储存<br>
这里是典型做法:</p>
<ol>
<li>先取其地址</li>
<li><strong>强制类型</strong>转化为<em><strong>int</strong></em>类型的指针</li>
<li>取这个<em><strong>int</strong></em>指针的值</li>
</ol>
<p>最终结果符合预期</p>
<h4 id="优缺点">优缺点</h4>
<p><strong>优点</strong>:</p>
<ul>
<li>可以直接通过位段的成员名称访问目标值</li>
</ul>
<p><em><strong>缺点</strong></em>:</p>
<ul>
<li>结构中位的排列方式是由编译器决定的(大端小端)<br>
因此不具有<em>可移植性</em></li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>L12_文件处理___2023-02-04</title>
			<link>https://zhydada.github.io/posts/l12_%E6%96%87%E4%BB%B6%E5%A4%84%E7%90%86___2023-02-04/</link>
			<pubDate>Sat, 04 Feb 2023 22:10:07 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l12_%E6%96%87%E4%BB%B6%E5%A4%84%E7%90%86___2023-02-04/</guid>
			<description>目录 格式化输入输出 输出的格式字符串 flags width和.prec h|L type 输入的格式字符串 flag type printf和scanf的返回值 文件的输入输出 FILE 操作文件的</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA">格式化输入输出</a>
<ul>
<li><a href="#%E8%BE%93%E5%87%BA%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%AD%97%E7%AC%A6%E4%B8%B2">输出的格式字符串</a>
<ul>
<li><a href="#flags">flags</a></li>
<li><a href="#width%E5%92%8Cprec">width和.prec</a></li>
<li><a href="#hl">h|L</a></li>
<li><a href="#type">type</a></li>
</ul>
</li>
<li><a href="#%E8%BE%93%E5%85%A5%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%AD%97%E7%AC%A6%E4%B8%B2">输入的格式字符串</a>
<ul>
<li><a href="#flag">flag</a></li>
<li><a href="#type-1">type</a></li>
</ul>
</li>
<li><a href="#printf%E5%92%8Cscanf%E7%9A%84%E8%BF%94%E5%9B%9E%E5%80%BC">printf和scanf的返回值</a></li>
</ul>
</li>
<li><a href="#%E6%96%87%E4%BB%B6%E7%9A%84%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA">文件的输入输出</a>
<ul>
<li><a href="#file">FILE</a>
<ul>
<li><a href="#%E6%93%8D%E4%BD%9C%E6%96%87%E4%BB%B6%E7%9A%84%E5%87%BD%E6%95%B0">操作文件的函数</a></li>
<li><a href="#%E6%89%93%E5%BC%80%E6%96%87%E4%BB%B6%E7%9A%84%E6%A0%87%E5%87%86%E4%BB%A3%E7%A0%81">打开文件的标准代码</a></li>
</ul>
</li>
<li><a href="#%E5%87%BD%E6%95%B0">函数</a>
<ul>
<li><a href="#fopen">fopen</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6">二进制文件</a>
<ul>
<li><a href="#%E9%80%89%E6%8B%A9%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E8%BF%98%E6%98%AF%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E7%9A%84%E5%8E%86%E5%8F%B2">选择文本文件还是二进制文件的历史</a></li>
<li><a href="#%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E5%92%8C%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E7%9A%84%E6%AF%94%E8%BE%83">文本文件和二进制文件的比较</a></li>
<li><a href="#%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E6%96%87%E4%BB%B6">程序运行为什么需要文件</a></li>
<li><a href="#%E6%93%8D%E4%BD%9C%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6">操作二进制文件</a>
<ul>
<li><a href="#%E8%AF%BB%E5%86%99">读写</a></li>
<li><a href="#%E5%AE%9A%E4%BD%8D">定位</a></li>
</ul>
</li>
<li><a href="#%E5%8F%AF%E7%A7%BB%E6%A4%8D%E6%80%A7%E9%97%AE%E9%A2%98">可移植性问题</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="格式化输入输出">格式化输入输出</h2>
<h3 id="输出的格式字符串">输出的格式字符串</h3>
<p>格式字符串有4个可选的参数<br>
完整的格式字符串是这样的:<br>
<code>%[flags][width][.prec][h|L]type</code></p>
<h4 id="flags">flags</h4>
<p><em><strong>flags</strong></em>是一个标志, 控制数字输出的样式<br>
有这样一些可选项  </p>
<table>
<thead>
<tr>
<th style="text-align:center">flags</th>
<th style="text-align:center">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>-</code></td>
<td style="text-align:center">左对齐</td>
</tr>
<tr>
<td style="text-align:center"><code>+</code></td>
<td style="text-align:center">显示正负号</td>
</tr>
<tr>
<td style="text-align:center">空格</td>
<td style="text-align:center">正数留空</td>
</tr>
<tr>
<td style="text-align:center"><code>0</code></td>
<td style="text-align:center">用零填充多余的位置</td>
</tr>
</tbody>
</table>
<blockquote>
<p>注意, 一个格式字符串可以有很多<em><strong>flags</strong></em><br>
这些<em><strong>flags</strong></em>的先后顺序无关紧要<br>
例如<code>printf(&quot;%+-9d&quot;,123);</code>就会输出左对齐的<code>+123</code><br>
<strong>但是</strong>, <em>左对齐</em>, <em>正数留空</em> 和 <em>用零填充</em> 这三个需求是冲突的, 只能出现一个</p>
</blockquote>
<h4 id="width和prec">width和.prec</h4>
<p><em><strong>width</strong></em>是一个正整数, 表示输出的数字总共所占据的字符的个数<br>
<em><strong>.prec</strong></em>是加在<em><strong>width</strong></em>前面的小数点, 表示输出的数字保留小数点后的个数</p>
<p>注意:</p>
<ul>
<li><code>%9.2d</code>表示总共是9个字符位, 小数点后保留两位</li>
</ul>
<blockquote>
<p>不要把<code>%9.2d</code>误当做是小数点前有9位的意思!</p>
</blockquote>
<ul>
<li><em><strong>width</strong></em>还可以是一个星号<code>*</code>, 让一个参数传入来作为width的值</li>
</ul>
<p>举例:</p>
<pre tabindex="0"><code>int len1 = 10;
int len2 = 2;
printf(&#34;下面这个数字共%d位, 保留了%d位小数点\n-&gt;|%+0*.*f|-&lt;&#34;, len1, len2, len1, len2, 123.4);
</code></pre><p>其输出为:</p>
<pre tabindex="0"><code>下面这个数字共10位, 保留了2位小数点
-&gt;|+000123.40|-&lt;
</code></pre><h4 id="hl">h|L</h4>
<p><em><strong>h|L</strong></em>是对类型的修饰  </p>
<table>
<thead>
<tr>
<th style="text-align:center">类型修饰</th>
<th style="text-align:center">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>hh</code></td>
<td style="text-align:center">单个字节</td>
</tr>
<tr>
<td style="text-align:center"><code>h</code></td>
<td style="text-align:center"><code>short</code></td>
</tr>
<tr>
<td style="text-align:center"><code>l</code>(小写L)</td>
<td style="text-align:center"><code>long</code></td>
</tr>
<tr>
<td style="text-align:center"><code>ll</code>(小写L)</td>
<td style="text-align:center"><code>long long</code></td>
</tr>
<tr>
<td style="text-align:center"><code>L</code></td>
<td style="text-align:center"><code>long double</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p>事实上并未生效, 能生效的只有<code>h</code>和<code>l</code>两个<br>
<code>hh</code>要实现的效果似乎可以直接用<code>c</code>替代, 就是输出最短的数据类型<br>
这里有个有趣的现象: <code>printf(&quot;%c&quot;, 12345);</code>输出的结果是<code>9</code></p>
<blockquote>
<p>这是因为<code>12345</code>在内存中储存为16进制的形式<code>0x3039</code><br>
只取最后一位, 以字符形式输出就是<code>9</code></p>
</blockquote>
</blockquote>
<h4 id="type">type</h4>
<p>汇总一下所有的类型  </p>
<table>
<thead>
<tr>
<th style="text-align:center">type</th>
<th style="text-align:center">用于</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>i</code>或者<code>d</code></td>
<td style="text-align:center"><code>int</code></td>
</tr>
<tr>
<td style="text-align:center"><code>u</code></td>
<td style="text-align:center"><code>unsigned int</code></td>
</tr>
<tr>
<td style="text-align:center"><code>o</code></td>
<td style="text-align:center">八进制</td>
</tr>
<tr>
<td style="text-align:center"><code>x</code></td>
<td style="text-align:center">字母小写的十六进制</td>
</tr>
<tr>
<td style="text-align:center"><code>X</code></td>
<td style="text-align:center">字母大写的十六进制</td>
</tr>
<tr>
<td style="text-align:center"><code>f</code>或者<code>F</code></td>
<td style="text-align:center">浮点数(到小数点后6位)</td>
</tr>
<tr>
<td style="text-align:center"><code>e</code>或者<code>E</code></td>
<td style="text-align:center">用科学计数法/指数形式表示, 大小写对应输出的&quot;e&quot;的大小写</td>
</tr>
<tr>
<td style="text-align:center"><code>g</code>或者<code>G</code></td>
<td style="text-align:center">保留6位有效数字的浮点</td>
</tr>
<tr>
<td style="text-align:center"><code>a</code>或者<code>A</code></td>
<td style="text-align:center">十六进制浮点</td>
</tr>
<tr>
<td style="text-align:center"><code>c</code></td>
<td style="text-align:center"><code>char</code></td>
</tr>
<tr>
<td style="text-align:center"><code>s</code></td>
<td style="text-align:center">字符串</td>
</tr>
<tr>
<td style="text-align:center"><code>p</code></td>
<td style="text-align:center">指针</td>
</tr>
<tr>
<td style="text-align:center"><code>n</code></td>
<td style="text-align:center">读入/写出的个数</td>
</tr>
</tbody>
</table>
<pre tabindex="0"><code>int num=0;
printf(&#34;-&gt;|%d|&lt;-%n\n&#34;, 12345, &amp;num);
printf(&#34;%d&#34;, num);
</code></pre><p>输出结果是:</p>
<pre tabindex="0"><code>-&gt;|12345|&lt;-
11
</code></pre><blockquote>
<p>笔者在VSC没有成功生效(虽然但是也没warning)</p>
</blockquote>
<h3 id="输入的格式字符串">输入的格式字符串</h3>
<p>相较于输出, 输入可选的参数比较简单<br>
其格式字符串是这样的: <code>%[flag]type</code></p>
<h4 id="flag">flag</h4>
<table>
<thead>
<tr>
<th style="text-align:center">flag</th>
<th style="text-align:center">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>*</code></td>
<td style="text-align:center">跳过一项</td>
</tr>
<tr>
<td style="text-align:center">数字</td>
<td style="text-align:center">最大读入的字符数</td>
</tr>
<tr>
<td style="text-align:center"><code>hh</code></td>
<td style="text-align:center">作为字符读入<code>char</code></td>
</tr>
<tr>
<td style="text-align:center"><code>h</code></td>
<td style="text-align:center"><code>short</code></td>
</tr>
<tr>
<td style="text-align:center"><code>l</code>(小写L)</td>
<td style="text-align:center"><code>long</code>或者<code>double</code></td>
</tr>
<tr>
<td style="text-align:center"><code>ll</code>(小写L)</td>
<td style="text-align:center"><code>long long</code></td>
</tr>
<tr>
<td style="text-align:center"><code>L</code></td>
<td style="text-align:center"><code>long double</code></td>
</tr>
</tbody>
</table>
<p>举例:</p>
<pre tabindex="0"><code>int num=0;
scanf(&#34;%*d%d&#34;, &amp;num);
printf(&#34;%d&#34;, num);
</code></pre><p>输入输出:</p>
<pre tabindex="0"><code>输入: 12345 67890  
输出: 67890
</code></pre><h4 id="type-1">type</h4>
<table>
<thead>
<tr>
<th style="text-align:center">type</th>
<th style="text-align:center">用于</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>d</code></td>
<td style="text-align:center"><code>int</code></td>
</tr>
<tr>
<td style="text-align:center"><code>i</code></td>
<td style="text-align:center">整数, 可以是十/八/十六进制的(更灵活)</td>
</tr>
<tr>
<td style="text-align:center"><code>u</code></td>
<td style="text-align:center"><code>unsigned int</code></td>
</tr>
<tr>
<td style="text-align:center"><code>o</code></td>
<td style="text-align:center">八进制</td>
</tr>
<tr>
<td style="text-align:center"><code>x</code></td>
<td style="text-align:center">十六进制</td>
</tr>
<tr>
<td style="text-align:center"><code>a/e/f/g</code></td>
<td style="text-align:center"><code>float</code></td>
</tr>
<tr>
<td style="text-align:center"><code>c</code></td>
<td style="text-align:center"><code>char</code></td>
</tr>
<tr>
<td style="text-align:center"><code>s</code></td>
<td style="text-align:center">字符串</td>
</tr>
<tr>
<td style="text-align:center"><code>[...]</code></td>
<td style="text-align:center">所允许的字符(类似于正则表达式)</td>
</tr>
<tr>
<td style="text-align:center"><code>p</code></td>
<td style="text-align:center">指针</td>
</tr>
</tbody>
</table>
<p>举例1:</p>
<pre tabindex="0"><code>int n1 = 0;
int n2 = 0;
scanf(&#34;%i%i&#34;, &amp;n1, &amp;n2);
printf(&#34;%i %i&#34;, n1, n2);
</code></pre><p>输入输出:</p>
<pre tabindex="0"><code>输入: 0xab 012
输出: 171 10
</code></pre><p>举例2:</p>
<pre tabindex="0"><code>char n1[20] ;
char n2[20];
scanf(&#34;%*[^:]:%[^,],%[^.]&#34;, n1, n2);
printf(&#34;%s %s&#34;, n1, n2);
</code></pre><p>输入输出:</p>
<pre tabindex="0"><code>输入: 输入了两个数字:123,456.
输出: 123 456
</code></pre><blockquote>
<p>这里的<code>[^:]</code>是指: 在第一个<code>:</code>前(不包括<code>:</code>)所有的内容(视为字符串)<br>
其他两个<code>[^,]</code> <code>[^.]</code>同理<br>
分析一下这里的输入格式字符串:</p>
<ul>
<li>首先, <strong>跳过</strong>封号<code>:</code>前所有内容</li>
<li>读入封号<code>:</code></li>
<li>读入逗号<code>,</code>前所有内容, 作为字符串交给地址<code>n1</code></li>
<li>读入逗号<code>,</code></li>
<li>读入句号<code>.</code>前所有内容, 作为字符串交给地址<code>n2</code></li>
</ul>
</blockquote>
<blockquote>
<p><code>[...]</code>的作用不止这一个, 但网上一下子搜不到相关知识点orz<br>
有一篇blog讲的较为详细, 链接-&gt; <a href="https://www.bbsmax.com/A/rV57w1wV5P/">c语言学习笔记第四章——字符串和格式化输入、输出</a></p>
</blockquote>
<h3 id="printf和scanf的返回值">printf和scanf的返回值</h3>
<p><code>printf</code>会返回成功输出的 <strong>字符数</strong><br>
<code>scanf</code>会返回成功读入的 <strong>项目数</strong></p>
<p>在较为严格的项目中, 应当判断每次输入输出的返回值<br>
以确保程序运行中不会产生问题</p>
<p>举例:</p>
<pre tabindex="0"><code>int num = 0;
int s = 0, p = 0;
s=scanf(&#34;%i&#34;, &amp;num);
p=printf(&#34;%i\n&#34;,num);
printf(&#34;scanf返回值:%d\n&#34;,s);
printf(&#34;printf返回值:%d\n&#34;,p);
</code></pre><p>输入: <code>0xabc</code><br>
输出:</p>
<pre tabindex="0"><code>0xabc
2748
scanf返回值:1
printf返回值:5
</code></pre><blockquote>
<p>这里返回值为<code>5</code>, 因为回车符也算在其中</p>
</blockquote>
<h2 id="文件的输入输出">文件的输入输出</h2>
<h3 id="file">FILE</h3>
<p><em><strong>FILE</strong></em>是标准库中定义的<strong>结构</strong><br>
常用的是<strong>文件指针</strong>: <code>FILE *</code></p>
<blockquote>
<p>该结构的其他成员用来反映文件的相关信息</p>
</blockquote>
<h4 id="操作文件的函数">操作文件的函数</h4>
<ul>
<li><em><strong>fopen</strong></em>函数打开指定文件, 并返回一个FILE指针<br>
<code>FILE * fopen (const char * restrict path, const char * restrict mode);</code></li>
<li><em><strong>fclose</strong></em>函数关闭文件<br>
<code>int    fclose (FILE * stream);</code></li>
<li><em><strong>fscanf</strong></em>函数负责从文件中读入<br>
<code>int fscanf(FILE *__stream, const char *__format, ...)</code></li>
<li><em><strong>fscanf</strong></em>函数负责向文件中写入<br>
<code>int fprintf (FILE *__stream, const char *__format, ...)</code></li>
</ul>
<h4 id="打开文件的标准代码">打开文件的标准代码</h4>
<pre tabindex="0"><code>FILE *fp = fopen(&#34;file&#34;, &#34;r&#34;);
if (fp)
{
    fscanf(fp, ...);
    /* handler */
    fclose(fp);
}
else
{
    /* fp == null */
    printf(&#34;无法打开文件\n&#34;);
}
</code></pre><blockquote>
<p>如果找不到文件, <em><strong>fopen</strong></em>函数会返回<em><strong>null</strong></em></p>
</blockquote>
<h3 id="函数">函数</h3>
<h4 id="fopen">fopen</h4>
<p><em><strong>fopen</strong></em>的第一个参数是文件的<strong>路径</strong><br>
第二个变量是打开文件的方式, 下面这个表格是所有可选的方式  </p>
<table>
<thead>
<tr>
<th style="text-align:center">方式代号</th>
<th style="text-align:center">效果</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>r</code></td>
<td style="text-align:center">只读</td>
</tr>
<tr>
<td style="text-align:center"><code>r+</code></td>
<td style="text-align:center">读写, 从文件头开始</td>
</tr>
<tr>
<td style="text-align:center"><code>w</code></td>
<td style="text-align:center">只写, 不存在就新建, 存在就清空</td>
</tr>
<tr>
<td style="text-align:center"><code>w+</code></td>
<td style="text-align:center">读写, 不存在就新建, 存在就清空</td>
</tr>
<tr>
<td style="text-align:center"><code>a</code></td>
<td style="text-align:center">追加, 不存在就新建, 存在就从文件尾部开始</td>
</tr>
<tr>
<td style="text-align:center"><code>..x</code>(在其他代号的后面加x)</td>
<td style="text-align:center">只新建, 如果文件已经存在了就不能打开</td>
</tr>
</tbody>
</table>
<h2 id="二进制文件">二进制文件</h2>
<p>所有文件最终都是<strong>二进制</strong>的<br>
文本文件可以通过简单的方式实现读写<br>
但是二进制文件需要<strong>专门的程序</strong>来实现读写</p>
<h3 id="选择文本文件还是二进制文件的历史">选择文本文件还是二进制文件的历史</h3>
<p>Unix 喜欢使用文本文件来做数据存储和程序配置</p>
<blockquote>
<p>由于交互式终端的出现(在Unix之前), 人们更倾向于使用文本与计算机&quot;talk&quot;(交互)</p>
<p>Unix的<em><strong>shell</strong></em>提供了利于读写文本的小程序, 因此使用文本很方便</p>
</blockquote>
<p>Windows喜欢使用二进制文件</p>
<blockquote>
<p>DOS操作系统的发明来源于草根文化, 是设计者革新的发明, 完全出自对于计算机硬件的理解<br>
因此, DOS并不继承Unix的特点</p>
<p>用二进制的方式做输入输出更接近底层</p>
</blockquote>
<h3 id="文本文件和二进制文件的比较">文本文件和二进制文件的比较</h3>
<p>文本文件:</p>
<ul>
<li>优点
<ul>
<li>方便人类读写</li>
<li>跨平台(到哪儿都能用)</li>
</ul>
</li>
<li>缺点
<ul>
<li>输入输出需要格式化</li>
<li>运算和处理的开销较大</li>
</ul>
</li>
</ul>
<p>二进制文件:</p>
<ul>
<li>缺点
<ul>
<li>输入输出是直接的</li>
<li>程序读写无需计算, 速度很快</li>
</ul>
</li>
<li>缺点
<ul>
<li>人类读写困难</li>
<li>不支持跨平台(例如<em><strong>int</strong></em>这样的类型在不同操作系统中的长度不一样, 还有可能涉及到大小端的问题)</li>
</ul>
</li>
</ul>
<h3 id="程序运行为什么需要文件">程序运行为什么需要文件</h3>
<ol>
<li>配置信息
<ul>
<li>Unix采用文本</li>
<li>Windows用注册表记录</li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>注册表</strong>是一个很大的二进制文件, 所有文件的配置信息全部记录在其中</p>
</blockquote>
<ol start="2">
<li>数据存储
<ul>
<li>量大的数据可以使用<strong>数据库</strong>很轻松的存储</li>
</ul>
</li>
<li>媒体文件
<ul>
<li>媒体文件只能是二进制文件</li>
</ul>
</li>
</ol>
<blockquote>
<p>事实上, 程序基本都通过第三方的库来实现对文件的读写<br>
很少直接读写二进制文件</p>
</blockquote>
<h3 id="操作二进制文件">操作二进制文件</h3>
<h4 id="读写">读写</h4>
<p>实在要直接处理二进制文件, 则采用以下这对函数:</p>
<pre tabindex="0"><code>size_t fread (void * pointer, size_t size, size_t nitems, FILE * stream);
size_t fwrite (const void * pointer, size_t size, size_t nitems, FILE * stream);
</code></pre><p>参数表:</p>
<ol>
<li>指针, 指向要读写的内存</li>
<li>这块内存的大小</li>
<li>有几个这样的内存</li>
<li>文件指针</li>
</ol>
<p><strong>返回值</strong> 的是成功的读写的字节数</p>
<blockquote>
<p>第三个参数<code>nitems</code>( <em>number of items</em> )的作用是什么?<br>
一般对二进制文件的读写都是通过对一个结构变量的操作进行的<br>
<code>nitems</code>就是用来说明这次读写操作几个结构变量</p>
</blockquote>
<h4 id="定位">定位</h4>
<ul>
<li>得到现在文件中的位置(从文件开头到现在位置的字节数)<br>
<code>long  ftell (FILE * stream);</code></li>
<li>定位到指定的位置
<code>int   fseek (FILE * stream, long offset, int whence);</code></li>
</ul>
<p><em><strong>fseek</strong></em>这个函数有三个参数:</p>
<ol>
<li><code>stream</code>是FILE指针</li>
<li><code>offset</code>是偏移量, 也就是数到第几个字节</li>
<li><code>whence</code>是寻找的方式, 有三个选项(都是预定义的宏, 所以表现出来的是int)</li>
</ol>
<ul>
<li><code>SEEK_SET</code>: 从头开始找</li>
<li><code>SEEK_CUR</code>: 从当前位置开始找</li>
<li><code>SEEK_END</code>: 从尾巴开始从后向前找</li>
</ul>
<blockquote>
<p>一般从二进制文件中得到结构个数的方式如下:<br>
用<code>fseek(fp, 0L, SEEK_END);</code>可以<strong>移动到末尾</strong>(这里的<code>0L</code>是将数字<code>0</code>作为长整型<code>Long</code>的表达方式)<br>
然后再用<code>long size = ftell(fp);</code>就可以得到<strong>从头到尾的字节数</strong><br>
用这个<code>size</code>除以每一个结构的大小就可以得到这个文件中的<strong>结构个数</strong></p>
</blockquote>
<h3 id="可移植性问题">可移植性问题</h3>
<p>二进制文件不具有可以执行性</p>
<blockquote>
<p><em><strong>int</strong></em>在32位机的<strong>字节数</strong>与64位机的<strong>不一致</strong><br>
读写就是错误的</p>
</blockquote>
<p>解决方案之一是放弃使用<em><strong>int</strong></em><br>
转而使用<em><strong>typedef</strong></em>人为定义出具有<strong>明确字节数</strong>的自定义类型<br>
当然, 更好的方案还是<strong>使用文本</strong></p>
]]></content>
		</item>
		
		<item>
			<title>L11_编译预处理___2023-01-29</title>
			<link>https://zhydada.github.io/posts/l11_%E7%BC%96%E8%AF%91%E9%A2%84%E5%A4%84%E7%90%86___2023-01-29/</link>
			<pubDate>Sun, 29 Jan 2023 21:57:33 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l11_%E7%BC%96%E8%AF%91%E9%A2%84%E5%A4%84%E7%90%86___2023-01-29/</guid>
			<description>目录 编译预处理 编译预处理指令 预处理时究竟发生了什么 宏 定义宏 使用宏 没有值的宏 预定义的宏 像函数的宏 易错点 特点 大程序结构 多个C文件 编译单元 IDE 头文件</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E7%BC%96%E8%AF%91%E9%A2%84%E5%A4%84%E7%90%86">编译预处理</a>
<ul>
<li><a href="#%E7%BC%96%E8%AF%91%E9%A2%84%E5%A4%84%E7%90%86%E6%8C%87%E4%BB%A4">编译预处理指令</a></li>
<li><a href="#%E9%A2%84%E5%A4%84%E7%90%86%E6%97%B6%E7%A9%B6%E7%AB%9F%E5%8F%91%E7%94%9F%E4%BA%86%E4%BB%80%E4%B9%88">预处理时究竟发生了什么</a></li>
</ul>
</li>
<li><a href="#%E5%AE%8F">宏</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E5%AE%8F">定义宏</a></li>
<li><a href="#%E4%BD%BF%E7%94%A8%E5%AE%8F">使用宏</a></li>
<li><a href="#%E6%B2%A1%E6%9C%89%E5%80%BC%E7%9A%84%E5%AE%8F">没有值的宏</a></li>
<li><a href="#%E9%A2%84%E5%AE%9A%E4%B9%89%E7%9A%84%E5%AE%8F">预定义的宏</a></li>
<li><a href="#%E5%83%8F%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%8F">像函数的宏</a>
<ul>
<li><a href="#%E6%98%93%E9%94%99%E7%82%B9">易错点</a></li>
<li><a href="#%E7%89%B9%E7%82%B9">特点</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%A4%A7%E7%A8%8B%E5%BA%8F%E7%BB%93%E6%9E%84">大程序结构</a>
<ul>
<li><a href="#%E5%A4%9A%E4%B8%AAc%E6%96%87%E4%BB%B6">多个C文件</a></li>
<li><a href="#%E7%BC%96%E8%AF%91%E5%8D%95%E5%85%83">编译单元</a></li>
<li><a href="#ide">IDE</a></li>
</ul>
</li>
<li><a href="#%E5%A4%B4%E6%96%87%E4%BB%B6">头文件</a>
<ul>
<li><a href="#%E4%BD%BF%E7%94%A8">使用</a></li>
<li><a href="#%E9%A2%84%E5%A4%84%E7%90%86%E6%8C%87%E4%BB%A4">预处理指令</a></li>
<li><a href="#%E4%BD%BF%E7%94%A8%E7%9A%84%E7%BB%86%E8%8A%82">使用的细节</a></li>
<li><a href="#%E8%AF%AF%E5%8C%BA">误区</a></li>
<li><a href="#%E5%A4%B4%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E8%A7%84%E8%8C%83">头文件的使用规范</a>
<ul>
<li><a href="#%E4%B8%8D%E5%AF%B9%E5%A4%96%E5%85%AC%E5%BC%80%E7%9A%84%E5%87%BD%E6%95%B0%E5%92%8C%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F">不对外公开的函数和全局变量</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F">全局变量</a>
<ul>
<li><a href="#%E5%A3%B0%E6%98%8E">声明</a></li>
<li><a href="#%E5%A3%B0%E6%98%8E%E5%92%8C%E5%AE%9A%E4%B9%89">声明和定义</a></li>
</ul>
</li>
<li><a href="#%E5%A4%B4%E6%96%87%E4%BB%B6%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF">头文件那些事儿</a>
<ul>
<li><a href="#%E8%A7%84%E5%88%99">规则</a></li>
<li><a href="#%E9%97%AE%E9%A2%98">问题</a></li>
<li><a href="#%E6%A0%87%E5%87%86%E5%A4%B4%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84">标准头文件结构</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="编译预处理">编译预处理</h2>
<h3 id="编译预处理指令">编译预处理指令</h3>
<p>所有预处理指令都以<code>#</code>开头</p>
<blockquote>
<p>&ldquo;#&ldquo;对应的英文是&quot;pound&rdquo;<br>
电话键盘上的&rdquo;#&ldquo;则是&quot;hash&rdquo;</p>
</blockquote>
<p><strong>注意</strong>: 编译预处理部分并不是C语言的成分(例如<em><strong>include</strong></em>不是C语言的关键字), 但是C语言程序离不开他们</p>
<h3 id="预处理时究竟发生了什么">预处理时究竟发生了什么</h3>
<p>编译C语言代码时, 编译器会产生一系列临时文件<br>
按照顺序来看, <code>.c</code>-&gt;<code>.i</code>-&gt;<code>.s</code>-&gt;<code>.o</code>-&gt;<code>.exe</code></p>
<ul>
<li>第一步, 首先编译<strong>预处理</strong>, 所有预处理完成后产生<code>.i</code>中间结果文件(注释也会被忽略掉)</li>
<li>第二步, 真正由C语言编译器<strong>编译</strong>, 产生<code>.s</code>汇编代码文件</li>
<li>第三步, 由汇编代码文件<strong>汇编</strong>, 产生<code>.o</code>目标代码文件</li>
<li>第四步, 根据链接, 将多个目标代码文件<strong>链接</strong>起来, 产生<code>.exe</code>可执行文件(linux是<code>.out</code>)</li>
</ul>
<h2 id="宏">宏</h2>
<h3 id="定义宏">定义宏</h3>
<p><code>#define</code>指令的作用是定义<strong>宏</strong><br>
<code>#define PI 3.1415926</code><br>
上面的这个指令定义了一个宏, <code>PI</code>是这个宏的<strong>名字</strong>, <code>3.1415926</code>是这个宏的<strong>值</strong></p>
<blockquote>
<p>可以理解为, <code>PI</code>是个<strong>符号</strong>, <strong>宏</strong>是他的具有高级感的别名</p>
</blockquote>
<blockquote>
<p>在编译预处理中, 在代码中出现的所有的宏的名字都会被<strong>直接替换</strong>为对应的值(换言之, 是 <em>原始的/直接的/原封不动</em> 的文本替换工作)</p>
</blockquote>
<p><strong>注意</strong></p>
<ul>
<li>宏的定义<strong>不是C语言代码</strong>, 因此后面不要加<code>;</code>封号</li>
</ul>
<h3 id="使用宏">使用宏</h3>
<ul>
<li>如果一个宏中有其他的宏的名字, 同样会被替换</li>
<li>如果宏的值超过一行, 需要在最后一行之前的行末加上<code>\</code>反斜杠</li>
<li>宏的值后面<strong>可以写注释</strong>, 不会被当做是宏的值</li>
</ul>
<pre tabindex="0"><code>#define HW &#34;Hello world!&#34; // 你好世界
#define PRT                \
    printf(&#34;你好世界!\n&#34;); \
    printf(&#34;%s&#34;, HW)

int main()
{
    PRT;
    return 0;
}
</code></pre><blockquote>
<p>注意观察<code>;</code><br>
因为在C语言代码中, 每一行指令最后要带有<strong>封号结尾</strong><br>
因此宏的名字后面要加封号的话, 宏的值最后不能有封号<br>
但是, 对于这种用来替代成段代码的宏, 其值就是代码<br>
因此该写封号还得写</p>
</blockquote>
<blockquote>
<p>总的一句, <strong>宏的值最后不能有封号</strong></p>
</blockquote>
<h3 id="没有值的宏">没有值的宏</h3>
<p>这一类宏的存在只想说明一件事: <strong>这个宏被定义过了</strong><br>
会有其他预处理指令通过这一点判断&quot;这个宏是否被定义&quot;<br>
这样就能实现&quot;条件编译&quot;(视情况而编译不同的代码)</p>
<h3 id="预定义的宏">预定义的宏</h3>
<table>
<thead>
<tr>
<th style="text-align:center">宏的名称</th>
<th style="text-align:center">宏的值</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>__LINE__</code></td>
<td style="text-align:center">当前代码所在的行号</td>
</tr>
<tr>
<td style="text-align:center"><code>__FILE__</code></td>
<td style="text-align:center">源代码文件的文件名(全路径)</td>
</tr>
<tr>
<td style="text-align:center"><code>__DATE__</code></td>
<td style="text-align:center">编译时的日期</td>
</tr>
<tr>
<td style="text-align:center"><code>__TIME__</code></td>
<td style="text-align:center">编译时的时间</td>
</tr>
</tbody>
</table>
<blockquote>
<p>注意, 这里的<code>__LINE__</code>是个整数, 其余都是<strong>字符串</strong></p>
</blockquote>
<h3 id="像函数的宏">像函数的宏</h3>
<p>名字中带有圆括号的宏能实现类似于函数的功能<br>
这样的宏可以带有参数<br>
<code>#define cube(x) ((x)*(x)*(x))</code><br>
<strong>注意</strong>: 圆括号中的参数 <strong>没有类型</strong></p>
<blockquote>
<p>这里仍旧是纯粹的文本替换!!!<br>
例如<code>cube(i+5)</code>会转变为:<br>
<code>((i+5)*(i+5)*(i+5))</code></p>
</blockquote>
<h4 id="易错点">易错点</h4>
<p>这种函数宏<strong>很容易犯错!!!</strong><br>
例如<code>#define DOUBLE(x) x+x</code><br>
在计算<code>3*DOUBLE(2)</code>的时候就会得到<code>8</code>这种错误答案</p>
<blockquote>
<p>错误的原因就是被替换的结果是<code>3*2+2</code>, 显然运算优先级被搅乱了</p>
</blockquote>
<p>因此, <strong>一切都要带括号</strong></p>
<ul>
<li>整个值要有括号</li>
<li>参数出现的每一处都要有括号</li>
</ul>
<p>此外, 函数宏可以有<strong>多个参数</strong>, 同样也可以嵌套使用其他宏</p>
<h4 id="特点">特点</h4>
<p>带参数的宏在大型程序的代码中使用极为普遍<br>
因为其处理效率比函数更高(更直接), 但代码大小会更大, 是牺牲空间换取效率的方式<br>
在<code>#</code>和<code>##</code>两个运算符的帮助下, 甚至可以实现&quot;产生&quot;函数的功能(函数工厂)<br>
使用宏的习惯上存在着中西方差异(外国人更习惯于使用宏)<br>
宏的弊端是, 宏不会检查数据类型<br>
拓展来说, <em><strong>inline</strong></em>函数可以取代宏的功能(会检查类型)</p>
<h2 id="大程序结构">大程序结构</h2>
<h3 id="多个c文件">多个C文件</h3>
<blockquote>
<p>一个<em><strong>main</strong></em>太长, 于是分出多个函数<br>
一个C源代码太长了, 于是也想分成多个文件<br>
但问题就在于, 多个文件不能直接被编译为可执行文件</p>
</blockquote>
<p>一些软件(如Dev C++), 可以新建一个项目, 在项目中加入多个源代码<br>
在编译时, 所有源代码文件都会被链接起来, 编译为一个可执行文件</p>
<h3 id="编译单元">编译单元</h3>
<p>一个<code>.c</code>文件是一个 <strong>编译单元</strong><br>
编译器每次编译只处理一个编译单元</p>
<h3 id="ide">IDE</h3>
<p><strong>IDE</strong>(集成开发环境 Integrated Development Environment)中一般会有两个功能</p>
<ul>
<li>编译(compile) 负责处理一个编译单元, 形成<code>.o</code>文件</li>
<li>构建(build) 负责将所有<code>.o</code>文件链接起来, 形成最终的可执行文件</li>
</ul>
<blockquote>
<p>Dev C++是一个传统的IDE, 上述两个功能在这个软件中被合并了</p>
</blockquote>
<h2 id="头文件">头文件</h2>
<h3 id="使用">使用</h3>
<p>将<strong>函数原型</strong>放在一个头文件(<code>.h</code>文件)中</p>
<blockquote>
<p>相当于是跨文件的声明</p>
</blockquote>
<p>在需要调用函数的源代码(<code>.c</code>文件)中调用时, 在头部加入<br>
<code>#include &quot;function.h&quot;</code><br>
这么做可以让编译器在编译时检查函数的原型声明</p>
<blockquote>
<p>头文件可以看做是个桥梁, 有助于检查函数的原型和使用</p>
</blockquote>
<h3 id="预处理指令">预处理指令</h3>
<p><code>#include</code>和宏一样, 也是一个<em>编译预处理指令</em><br>
也和宏一样, <em><strong>include</strong></em>实质上只是把<code>.h</code>文件<strong>原封不动</strong>的搬到了<code>.i</code>文件头部的位置</p>
<blockquote>
<p>终究只是个搬运工</p>
</blockquote>
<h3 id="使用的细节">使用的细节</h3>
<p><code>#include</code>有<em>两种</em>寻找文件的方式<br>
分别是: 双引号<code>&quot;&quot;</code> 和 尖括号<code>&lt;&gt;</code><br>
其<strong>区别</strong>是:</p>
<ul>
<li>双引号<code>&quot;&quot;</code>会<strong>优先在当前目录</strong>下寻找文件, 如果找不到, 再到系统路径中寻找</li>
<li>尖括号<code>&lt;&gt;</code>直接去系统路径中寻找</li>
</ul>
<p>因此, 一般来说, 系统标准库提供的头文件使用尖括号<code>&lt;&gt;</code>, 自己定义的头文件使用双引号<code>&quot;&quot;</code></p>
<blockquote>
<p><em>系统指定的目录</em>一般是指环境变量, 且编译器自己知道</p>
</blockquote>
<h3 id="误区">误区</h3>
<p><code>#include</code>其实不是用来引入库的, ta只是用来原封不动的搬运代码</p>
<blockquote>
<p><code>.h</code>中只有个原型, 其中定义的如<em><strong>printf</strong></em>这类函数的源代码在某个<code>.lib</code>文件(Windows)或是<code>.a</code>文件(Unix)中<br>
在编译时, 这些东西会由编译器自动链接进去</p>
<blockquote>
<p>这也就解释了, 为什么, 不引入头文件使用函数, 只会warning但函数仍旧正常工作<br>
这是因为只是原型丢失(给warning), 编译器会去猜原型, 正好猜中了, 于是正常运行</p>
</blockquote>
</blockquote>
<p>之所以要做<code>#include &lt;stdio.h&gt;</code>这个动作, 只是为了让编译器知道函数的原型<br>
保证调用的时候给出的数据类型正确</p>
<h3 id="头文件的使用规范">头文件的使用规范</h3>
<p>因此, 在使用和定义函数的时候都应当有头文件!</p>
<blockquote>
<p>规范的操作一般是<code>function.c</code>和<code>function.h</code>两个文件成对出现</p>
</blockquote>
<p>头文件中一般包含:</p>
<ul>
<li>所有公开的函数的原型</li>
<li>所有全局变量的声明</li>
</ul>
<blockquote>
<p>全局变量是可以在多个<code>.c</code>文件中共享的</p>
</blockquote>
<h4 id="不对外公开的函数和全局变量">不对外公开的函数和全局变量</h4>
<p>如果希望一个函数只在这一个<code>.c</code>文件中使用<br>
可以字啊函数声明前加上<em><strong>static</strong></em>关键字<br>
那么这个函数只能在当前的编译单元中使用<br>
这样不对外公开的函数一般称为局部函数</p>
<blockquote>
<p>局部的全局变量也是同理</p>
<blockquote>
<p>注意ta仍旧是<strong>全局变量</strong>, 只是在这个文件中被使用, 所以叫局部的全局变量</p>
</blockquote>
</blockquote>
<h2 id="全局变量">全局变量</h2>
<h3 id="声明">声明</h3>
<p>和函数一样, 要使得一个项目中所有的<code>.c</code>文件都能访问到公用的全局变量<br>
同样也要做出 <strong>声明</strong></p>
<blockquote>
<p>变量的声明是为了让程序知道变量的<strong>类型</strong><br>
因为只有知道了变量类型, 才能让函数在处理变量前有所准备</p>
</blockquote>
<p>声明在头文件中实现, 语法如下<br>
<code>extern int number;</code></p>
<h3 id="声明和定义">声明和定义</h3>
<p>要区别开变量的 <em>声明</em> 和 <em>定义</em></p>
<ul>
<li>定义: <code>int i = 0;</code></li>
<li>声明: <code>extern int i;</code></li>
</ul>
<blockquote>
<p>声明的时候<strong>不能初始化!</strong><br>
那是定义的时候干的事情</p>
</blockquote>
<p><strong>声明</strong>这个行为是 <strong>不会产生代码</strong> 的<br>
能够被声明的东西有很多:</p>
<ul>
<li>函数原型</li>
<li>变量声明</li>
<li>结构声明</li>
<li>宏声明</li>
<li>枚举声明</li>
<li>类型声明</li>
<li>inline函数</li>
</ul>
<p>相对应的, <strong>定义</strong>会产生代码<br>
而能被定义的只有:</p>
<ul>
<li>函数定义</li>
<li>变量定义</li>
</ul>
<p>除此以外都不会产生代码</p>
<blockquote>
<p>所谓 <strong>产生代码</strong>, 就是编译器要去编译从而形成可执行的指令 <br>
而当编译器看到声明的时候, ta只会去做一个类似于<em>登记</em>的行为<br>
以便在编译实质性代码的时候明确变量等的类型</p>
</blockquote>
<h2 id="头文件那些事儿">头文件那些事儿</h2>
<h3 id="规则">规则</h3>
<p><strong>只有声明可以被写入头文件!!!</strong></p>
<blockquote>
<p>上面这条只是<em>规则</em>, 算不上是<em>法律</em></p>
</blockquote>
<p>如果不这么做会造成一个项目中出现<strong>多个编译单元</strong>中有<strong>重名实体</strong>的情况<br>
这很可能产生问题</p>
<h3 id="问题">问题</h3>
<p>对于<em>结构</em>而言, 其声明<strong>不得重复</strong><br>
但是在复杂的程序结构中, 一个头文件被多次引用的情况非常常见, 甚至是难以避免的<br>
下面就是个常见的例子:</p>
<blockquote>
<p>头文件&quot;A.h&quot;</p>
</blockquote>
<pre tabindex="0"><code>typedf struct point{
  int x;
  int y;
} Point;
</code></pre><blockquote>
<p>头文件&quot;B.h&quot;</p>
</blockquote>
<pre tabindex="0"><code>#include &#34;A.h&#34;
extern int NUMBER;
</code></pre><blockquote>
<p>总程序&quot;main.c&quot;</p>
</blockquote>
<pre tabindex="0"><code>#include &#34;A.h&#34;
#include &#34;B.h&#34;

int main(){
  /* code here */
  return 0;
}
</code></pre><p>此时, 依据前文的特性, 编译预处理完成后的实际代码是这样的:</p>
<pre tabindex="0"><code>typedf struct point{
  int x;
  int y;
} Point;

typedf struct point{
  int x;
  int y;
} Point;
extern int NUMBER;

int main(){
  /* code here */
  return 0;
}
</code></pre><p>显然, 结构被重复定义了, 自然少不了报错</p>
<h3 id="标准头文件结构">标准头文件结构</h3>
<p>运用<strong>条件编译</strong>和<strong>宏</strong>的配合, 就能保证一个头文件实际只会被<em><strong>include</strong></em>一次<br>
具体语法如下:</p>
<pre tabindex="0"><code>#ifndef __A_HEAD__
#define __A_HEAD__

typedf struct point{
  int x;
  int y;
} Point;

#endif
</code></pre><blockquote>
<p>之所以这个宏的左右带上了双下划线<br>
是为了保证不和正常的宏<strong>冲突</strong><br>
这也是程序员的约定俗成的习惯</p>
</blockquote>
<blockquote>
<p>在<em><strong>Visual Studio</strong></em>中, <code>#pragma once</code>也可以起到相同的效果<br>
但是不是所有编译器都支持</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>L10_枚举和结构___2022-12-28</title>
			<link>https://zhydada.github.io/posts/l10_%E6%9E%9A%E4%B8%BE%E5%92%8C%E7%BB%93%E6%9E%84___2022-12-28/</link>
			<pubDate>Wed, 28 Dec 2022 22:11:28 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l10_%E6%9E%9A%E4%B8%BE%E5%92%8C%E7%BB%93%E6%9E%84___2022-12-28/</guid>
			<description>目录 枚举 引入 概念 语法 说明 套路 枚举量 枚举只是int 小总结 结构 声明 注意点 初始化 调用 运算 结构指针 结构与函数 结构作为函数的参数和返回值 输入结构 错误示</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E6%9E%9A%E4%B8%BE">枚举</a>
<ul>
<li><a href="#%E5%BC%95%E5%85%A5">引入</a></li>
<li><a href="#%E6%A6%82%E5%BF%B5">概念</a></li>
<li><a href="#%E8%AF%AD%E6%B3%95">语法</a></li>
<li><a href="#%E8%AF%B4%E6%98%8E">说明</a></li>
<li><a href="#%E5%A5%97%E8%B7%AF">套路</a></li>
<li><a href="#%E6%9E%9A%E4%B8%BE%E9%87%8F">枚举量</a></li>
<li><a href="#%E6%9E%9A%E4%B8%BE%E5%8F%AA%E6%98%AFint">枚举只是int</a></li>
<li><a href="#%E5%B0%8F%E6%80%BB%E7%BB%93">小总结</a></li>
</ul>
</li>
<li><a href="#%E7%BB%93%E6%9E%84">结构</a>
<ul>
<li><a href="#%E5%A3%B0%E6%98%8E">声明</a></li>
<li><a href="#%E6%B3%A8%E6%84%8F%E7%82%B9">注意点</a></li>
<li><a href="#%E5%88%9D%E5%A7%8B%E5%8C%96">初始化</a></li>
<li><a href="#%E8%B0%83%E7%94%A8">调用</a></li>
<li><a href="#%E8%BF%90%E7%AE%97">运算</a></li>
<li><a href="#%E7%BB%93%E6%9E%84%E6%8C%87%E9%92%88">结构指针</a></li>
</ul>
</li>
<li><a href="#%E7%BB%93%E6%9E%84%E4%B8%8E%E5%87%BD%E6%95%B0">结构与函数</a>
<ul>
<li><a href="#%E7%BB%93%E6%9E%84%E4%BD%9C%E4%B8%BA%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0%E5%92%8C%E8%BF%94%E5%9B%9E%E5%80%BC">结构作为函数的参数和返回值</a></li>
<li><a href="#%E8%BE%93%E5%85%A5%E7%BB%93%E6%9E%84">输入结构</a>
<ul>
<li><a href="#%E9%94%99%E8%AF%AF%E7%A4%BA%E8%8C%83">错误示范</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E7%BB%93%E6%9E%84%E4%B8%AD%E7%9A%84%E7%BB%93%E6%9E%84">结构中的结构</a>
<ul>
<li><a href="#%E7%BB%93%E6%9E%84%E6%95%B0%E7%BB%84">结构数组</a></li>
<li><a href="#%E6%8C%87%E9%92%88">指针</a></li>
<li><a href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%9E%8B%E5%AE%9A%E4%B9%89">自定义类型定义</a></li>
</ul>
</li>
<li><a href="#%E8%81%94%E5%90%88">联合</a>
<ul>
<li><a href="#%E8%AF%AD%E6%B3%95-1">语法</a></li>
<li><a href="#%E7%89%B9%E7%82%B9">特点</a></li>
<li><a href="#%E7%94%A8%E6%B3%95">用法</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="枚举">枚举</h2>
<h3 id="引入">引入</h3>
<p>为了消除<em><strong>MagicWord</strong></em>, 我们会将一些字面量定义成<strong>常量</strong></p>
<blockquote>
<p>例如: <code>const char RED=&quot;#ff0000&quot;;</code></p>
</blockquote>
<p>但是考虑到会有多个同一方面(例如都是颜色)的常量<br>
我们引入<strong>枚举</strong>这个概念</p>
<h3 id="概念">概念</h3>
<p><strong>枚举</strong>是一种用户定义的<strong>数据类型</strong><br>
使用关键字 <em><strong>enum</strong></em> (全称: <em>enumeration</em>)</p>
<h3 id="语法">语法</h3>
<p>声明一个枚举类型<br>
<code>enum 枚举类型名字 {名字0, 名字1, ... 名字n}</code></p>
<blockquote>
<p>这里的&quot;名字&quot;被称为 <strong>枚举量</strong></p>
</blockquote>
<p>定义一个这种数据类型的变量<br>
<code>enum 枚举类型名字 变量名 = 名字i</code></p>
<blockquote>
<p>可以把这个<strong>枚举类型</strong>看作和<em><strong>int</strong></em>一样
在其他输入输出方面, 都和<em><strong>int</strong></em>一致</p>
</blockquote>
<h3 id="说明">说明</h3>
<ul>
<li><strong>枚举类型名字</strong>通常不会真的使用, 重要的是大括号中的名字</li>
<li>大括号中的名字相当于<strong>常量的变量名</strong></li>
<li>这些常量的类型必须是<em><strong>int</strong></em></li>
<li>初始值依次从<code>0</code>到<code>n</code></li>
<li><strong>枚举</strong>的实质就是<em><strong>int</strong></em>, ta的意义就是为了方便</li>
</ul>
<h3 id="套路">套路</h3>
<p>由于声明的时候是从<code>0</code>开始赋值的<br>
此时在最后一个名字的后面再加一个名字(一般是<code>numberofxxx</code>)<br>
那么ta的值就是符号的数量<br>
之后在处理循环的时候会很方便</p>
<h3 id="枚举量">枚举量</h3>
<p>声明枚举量的时候可以指定值<br>
没有被指定, 就接着前面的计数
<code>enum COLOR {RED = 3, YELLOW, GREEN=7};</code><br>
此时<code>YELLOW</code>的值就是<code>4</code></p>
<h3 id="枚举只是int">枚举只是int</h3>
<p>如果给枚举类型的变量赋予 不存在/没有意义的值/其他类型 的值<br>
不会报错</p>
<h3 id="小总结">小总结</h3>
<p>总而言之, 只有当名字在寓意上连贯有意义的情况<br>
也就是比起使用多次<code>const int</code>方便的时候<br>
才会选择使用枚举</p>
<h2 id="结构">结构</h2>
<blockquote>
<p>要用一个整体表示<br>
一个人的名字, 生日&hellip; <br>
时间的年月日&hellip;<br>
要使用结构类型</p>
</blockquote>
<h3 id="声明">声明</h3>
<ul>
<li>形式1:</li>
</ul>
<pre tabindex="0"><code>struct 结构类型{
    int 结构成员1;
    char 结构成员2;
    double 结构成员3;
};
struct 结构类型 结构变量1, 结构变量2;
</code></pre><ul>
<li>形式2:</li>
</ul>
<pre tabindex="0"><code>struct {
    int 结构成员1;
    char 结构成员2;
    double 结构成员3;
}结构变量1, 结构变量2;
</code></pre><blockquote>
<p>无名类型, 以后用不到</p>
</blockquote>
<ul>
<li>形式3:</li>
</ul>
<pre tabindex="0"><code>struct 结构类型{
    int 结构成员1;
    char 结构成员2;
    double 结构成员3;
}结构变量1, 结构变量2;
</code></pre><h3 id="注意点">注意点</h3>
<ul>
<li>声明结构类型也是一条语句, <strong>最后的分号不能漏</strong></li>
<li>在函数的内部声明结构, 出了函数就用不了, 一般在外部声明</li>
<li><em>声明结构类型</em> 和 <em>声明结构变量</em> 是两个操作, 在上面的形式1就分开了</li>
<li>单独声明结构变量的时候不能漏了操作符 <em><strong>struct</strong></em></li>
</ul>
<h3 id="初始化">初始化</h3>
<pre tabindex="0"><code>struct 结构类型 结构变量1 = {7, &#39;Z&#39;, 6.4};
struct 结构类型 结构变量2 = {.成员类型1=7, .成员类型3=6.4};
</code></pre><p>在第二种初始化的形式, 成员类型2没有赋予初始值, 会自动赋<code>0</code></p>
<h3 id="调用">调用</h3>
<p><code>int a = 结构变量1.结构成员1;</code></p>
<blockquote>
<p><code>.</code>也是一个运算符, 用来访问结构成员<br>
结构类型是一种类型, 对ta使用<code>.</code>没有意义</p>
</blockquote>
<h3 id="运算">运算</h3>
<p>对于整个<em>结构变量</em>, 可以做 赋值/取地址/作为参数传递 这些操作</p>
<pre tabindex="0"><code>结构变量1 = (struct point){5, &#39;b&#39;, 9.7};
结构变量2 = 结构变量1;
</code></pre><h3 id="结构指针">结构指针</h3>
<p>和数组有所区别, 结构变量的<strong>名字</strong>不是地址<br>
必须使用<code>&amp;</code>运算符取地址</p>
<h2 id="结构与函数">结构与函数</h2>
<h3 id="结构作为函数的参数和返回值">结构作为函数的参数和返回值</h3>
<p><code>type function_name(struct struct_name para)</code><br>
这个函数的参数是一个 <strong>结构变量</strong></p>
<ul>
<li><strong>整个结构</strong>可以作为<strong>参数的值</strong>传入函数</li>
<li>其实质是, 在函数内<strong>新建</strong>一个结构变量,<br>
并<strong>复制</strong>调用者的结构的值
<blockquote>
<p>函数内发生的不会影响传入的那个结构<br>
因为函数内部的是<strong>新的</strong>结构<br>
注意区别于数组</p>
</blockquote>
</li>
<li>可以<strong>返回结构</strong></li>
</ul>
<h3 id="输入结构">输入结构</h3>
<p>没有直接的方式可以一次<em><strong>scanf</strong></em>一个结构<br>
可以自己写一个函数实现</p>
<h4 id="错误示范">错误示范</h4>
<pre tabindex="0"><code>struct point
{
    int x;
    int y;
};

void inputStruct(struct point p);
void outputStruct(struct point p);

int main()
{
    struct point p0 = {0, 0};
    inputStruct(p0);
    outputStruct(p0);
    return 0;
}

void inputStruct(struct point p)
{
    scanf(&#34;%d&#34;, &amp;p.x);
    scanf(&#34;%d&#34;, &amp;p.y);
    printf(&#34;在inputStruct中:\n&#34;);
    printf(&#34;x: %d\ny: %d\n&#34;, p.x, p.y);
}
void outputStruct(struct point p)
{
    printf(&#34;在outputStruct中:\n&#34;);
    printf(&#34;x: %d\ny: %d\n&#34;, p.x, p.y);
}
</code></pre><p>输入:  <code>12 23</code>
输出结果:</p>
<pre tabindex="0"><code>12 23
在inputStruct中:
x: 12
y: 23
在outputStruct中:
x: 0
y: 0
</code></pre><p>这里<em><strong>main</strong></em>函数中定义的<code>p0</code>并未改变<br>
这是因为, 传入的参数是复制过去的<code>p</code>, 已经不是<code>p0</code>了</p>
<h2 id="结构中的结构">结构中的结构</h2>
<h3 id="结构数组">结构数组</h3>
<p><code>struct point points[] = {{x1,x2}, {1,2}, {0,0}};</code></p>
<blockquote>
<p>举例来说<br>
一个<strong>矩形</strong>可以用<em>左上角</em>和<em>右下角</em>两个<strong>点</strong>来确定<br>
每个<strong>点</strong>, 又是由两个<strong>坐标</strong>组成的<br>
这时候就产生了嵌套的结构, 此时定义一个矩形的方式如下</p>
</blockquote>
<pre tabindex="0"><code>struct point
{
    int x;
    int y;
};
struct rectangle{
    struct point pt1;
    struct point pt2;
};
struct rectangle r;
</code></pre><p>这里的<strong>矩形</strong> <code>r</code> 有四个值:</p>
<ul>
<li><code>r.pt1.x</code></li>
<li><code>r.pt1.y</code></li>
<li><code>r.pt2.x</code></li>
<li><code>r.pt2.y</code></li>
</ul>
<h3 id="指针">指针</h3>
<p>仍旧以矩形为例, 此时如果再定义一个<strong>矩形</strong>指针<code>*rp</code>:<br>
<code>struct rectangle r,*rp;</code><br>
那么有四个形式是等价的:</p>
<ul>
<li><code>r.pt1.x</code></li>
<li><code>rp-&gt;pt1.x</code></li>
<li><code>(r.pt1).x</code></li>
<li><code>(rp-&gt;pt1).x</code></li>
</ul>
<p>注意, 以下这个形式是错误的:</p>
<ul>
<li><code>rp-&gt;pt1-&gt;x</code></li>
</ul>
<blockquote>
<p>因为<code>pt1</code>是结构, 不是指针</p>
</blockquote>
<h3 id="自定义类型定义">自定义类型定义</h3>
<blockquote>
<p>在定义完一个结构之后, 每次使用都必须在前面加上<em><strong>struct</strong></em><br>
这给人以一种 <em>&ldquo;不是亲生&rdquo;</em> 的感觉&hellip;<br>
<em><strong>typedef</strong></em>就允许你&quot;真正&quot;使用自定义的数据类型</p>
</blockquote>
<p><em><strong>typedef</strong></em>用以声明一个已有数据类型的 <strong>别名</strong><br>
<code>typedef int Length;</code><br>
声明后, 两者用法一致</p>
<pre tabindex="0"><code>typedef struct ADate{...} Date;
Date d = {...};
</code></pre><blockquote>
<p>在使用结构时, <em><strong>typedef</strong></em>尤其方便
上面的例子中, <code>ADate</code>可以省略不写, 因为最后实际使用的是<code>Date</code></p>
</blockquote>
<h2 id="联合">联合</h2>
<p><strong>联合</strong> (<em><strong>union</strong></em>) 在表面上看起来与 <strong>结构</strong>(<em><strong>struct</strong></em>)是极为相似的</p>
<h3 id="语法-1">语法</h3>
<pre tabindex="0"><code>union Test
{
    int i;
    char c;
} union1, union2;
</code></pre><h3 id="特点">特点</h3>
<ul>
<li><em><strong>union</strong></em>的每个成员 <strong>都占据同一块空间</strong></li>
<li>对其中一个成员赋值, 会覆盖掉其他成员</li>
</ul>
<h3 id="用法">用法</h3>
<p>最常用的场合, 是查看数据在内存中的 <strong>储存形式</strong><br>
例如一个联合中有<code>i</code>和<code>char[sizeof(int)]</code>这两个成员<br>
当<code>i</code>中写入一个整数后, 可以通过遍历<code>char</code>数组查看<strong>每个字节的值</strong><br>
这有助于我们理解数据内部存储的情况<br>
同时, 在做文件处理时, 也可以用这种方式将数据转化为二进制处理</p>
]]></content>
		</item>
		
		<item>
			<title>L9_字符串___2022-12-18</title>
			<link>https://zhydada.github.io/posts/l9_%E5%AD%97%E7%AC%A6%E4%B8%B2___2022-12-18/</link>
			<pubDate>Sun, 18 Dec 2022 19:07:31 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l9_%E5%AD%97%E7%AC%A6%E4%B8%B2___2022-12-18/</guid>
			<description>目录 字符串 特殊的0 字符串变量 字符串常量 连接的两个字符字面量 小总结 字符串常量 采用数组 指针和数组的选择 字符串的有关操作 赋值 输入输出 读取的机制 安全</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2">字符串</a>
<ul>
<li><a href="#%E7%89%B9%E6%AE%8A%E7%9A%840">特殊的0</a></li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%98%E9%87%8F">字符串变量</a></li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F">字符串常量</a></li>
<li><a href="#%E8%BF%9E%E6%8E%A5%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E5%AD%97%E9%9D%A2%E9%87%8F">连接的两个字符字面量</a></li>
<li><a href="#%E5%B0%8F%E6%80%BB%E7%BB%93">小总结</a></li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F-1">字符串常量</a>
<ul>
<li><a href="#%E9%87%87%E7%94%A8%E6%95%B0%E7%BB%84">采用数组</a></li>
<li><a href="#%E6%8C%87%E9%92%88%E5%92%8C%E6%95%B0%E7%BB%84%E7%9A%84%E9%80%89%E6%8B%A9">指针和数组的选择</a></li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%9C%89%E5%85%B3%E6%93%8D%E4%BD%9C">字符串的有关操作</a>
<ul>
<li><a href="#%E8%B5%8B%E5%80%BC">赋值</a></li>
<li><a href="#%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA">输入输出</a>
<ul>
<li><a href="#%E8%AF%BB%E5%8F%96%E7%9A%84%E6%9C%BA%E5%88%B6">读取的机制</a></li>
<li><a href="#%E5%AE%89%E5%85%A8%E7%9A%84%E8%BE%93%E5%85%A5">安全的输入</a></li>
<li><a href="#%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF">常见错误</a></li>
<li><a href="#%E7%A9%BA%E5%AD%97%E7%AC%A6%E4%B8%B2">空字符串</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%95%B0%E7%BB%84">字符串数组</a>
<ul>
<li><a href="#%E4%B8%80%E4%BA%9B%E8%A1%A8%E8%BE%BE%E6%96%B9%E5%BC%8F">一些表达方式</a></li>
<li><a href="#%E7%A8%8B%E5%BA%8F%E5%8F%82%E6%95%B0">程序参数</a></li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E5%87%BD%E6%95%B0">字符函数</a>
<ul>
<li><a href="#%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6%E8%BE%93%E5%85%A5-putchar">单个字符输入 putchar</a>
<ul>
<li><a href="#%E8%AF%AD%E6%B3%95">语法</a></li>
<li><a href="#%E8%AF%B4%E6%98%8E">说明</a></li>
</ul>
</li>
<li><a href="#%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6%E8%BE%93%E5%87%BA-getchar">单个字符输出 getchar</a>
<ul>
<li><a href="#%E8%AF%AD%E6%B3%95-1">语法</a></li>
<li><a href="#%E8%AF%B4%E6%98%8E-1">说明</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0">字符串函数</a>
<ul>
<li><a href="#%E6%89%80%E7%94%A8%E7%9A%84%E5%BA%93">所用的库</a></li>
<li><a href="#strlen">strlen</a></li>
<li><a href="#strcmp">strcmp</a></li>
<li><a href="#strcpy">strcpy</a>
<ul>
<li><a href="#%E5%A4%8D%E5%88%B6%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2">复制一个字符串</a></li>
<li><a href="#%E5%8F%AF%E8%83%BD%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%BD%A2%E5%BC%8F">可能的实现形式</a></li>
</ul>
</li>
<li><a href="#strcat">strcat</a>
<ul>
<li><a href="#%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98">安全问题</a></li>
<li><a href="#%E5%AE%89%E5%85%A8%E7%9A%84%E7%89%88%E6%9C%AC">安全的版本</a></li>
</ul>
</li>
<li><a href="#strchr">strchr</a>
<ul>
<li><a href="#%E5%AF%BB%E6%89%BE%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%AD%97%E7%AC%A6">寻找第二个字符</a></li>
<li><a href="#%E5%BE%97%E5%88%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E9%85%8D%E5%AF%B9%E4%B9%8B%E5%89%8D%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2">得到第一个配对之前的字符串</a></li>
</ul>
</li>
<li><a href="#strstr">strstr</a></li>
</ul>
</li>
<li><a href="#%E5%85%B3%E4%BA%8E%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA-%E5%92%8C-shell%E7%9A%84%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86">关于输入输出 和 SHELL的一些知识</a>
<ul>
<li><a href="#%E4%BB%80%E4%B9%88%E6%98%AFshell">什么是SHELL?</a></li>
<li><a href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%95%B2%E5%9B%9E%E8%BD%A6%E7%A8%8B%E5%BA%8F%E6%89%8D%E7%BB%A7%E7%BB%AD">为什么敲回车程序才继续?</a></li>
<li><a href="#%E5%A6%82%E4%BD%95%E5%81%9C%E6%AD%A2%E8%BE%93%E5%85%A5">如何停止输入?</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="字符串">字符串</h2>
<p><code>char word1[]={'H', 'e', 'l', 'l', 'o', '!'};</code>被称为<strong>字符数组</strong>, 有意义, 但不是一个字符串<br>
在C语言中, 定义<strong>字符串</strong>是这样的: 
<code>char word2[]={'H', 'e', 'l', 'l', 'o', '!', '\0'};</code></p>
<p><strong>注意</strong>: <code>word2</code>首先是个字符数组, 但由于其中一个单元存在<code>'\0'</code>, 这使之称为了C语言的字符串</p>
<h3 id="特殊的0">特殊的0</h3>
<ol>
<li>整数<code>0</code>和字符<code>'\0'</code>等价</li>
<li>字符<code>'0'</code>对应整数<code>48</code></li>
</ol>
<pre tabindex="0"><code>char a = &#39;0&#39;;
char b = &#39;\0&#39;;
printf(&#34;a=%d\n&#34;, a);
printf(&#34;b=%d\n&#34;, b);
</code></pre><p>结果是:</p>
<pre tabindex="0"><code>a=48
b=0
</code></pre><ol start="3">
<li><code>'\0'</code>标志着字符串的结束, 但<strong>ta不属于该字符串</strong></li>
<li>计算字符串长度时, 不包括这个<code>'\0'</code>(当然, 作为数组时的长度, 以及在计算内存占用时, <strong>仍旧会包含在内</strong>)</li>
</ol>
<h3 id="字符串变量">字符串变量</h3>
<p>定义的语法有这样3种</p>
<pre tabindex="0"><code>char *str = &#34;Hello&#34;;
char word[] = &#34;Hello&#34;;
char line[10] = &#34;Hello&#34;;
</code></pre><blockquote>
<p>注意, 对于<code>word</code>来说, ta占据了6个字节, 最后的结束符<code>'\0'</code>会由编译器自动补上</p>
</blockquote>
<pre tabindex="0"><code>char word[] = &#34;Hello&#34;;
printf(&#34;sizeof(word)=%d\n&#34;, sizeof(word));
</code></pre><p>结果是:<br>
<code>sizeof(word)=6</code></p>
<h3 id="字符串常量">字符串常量</h3>
<p>形如<code>&quot;Hello&quot;</code>的带有双引号的字面量被称为 <strong>字符串常量</strong> 或是 <strong>字符串字面量</strong><br>
这样的字面量会被编译器编译为一个字符数组存放在别处</p>
<h3 id="连接的两个字符字面量">连接的两个字符字面量</h3>
<p>如果两个字符串是相邻的, 且中间没有其他符号, 编译器会自动将两者连接起来<br>
比如一下这个例子:</p>
<pre tabindex="0"><code>printf(&#34;The end is&#34;
        &#34; not the end.\n&#34;);
</code></pre><p>结果是:</p>
<pre tabindex="0"><code>The end is not the end.
</code></pre><p>此外, 还可以在字符串的中间换行断开, 并用反斜杠<code>\</code>承接<br>
但要注意的是, 这样会把制表符一起混进去</p>
<pre tabindex="0"><code>int main()
{
    printf(&#34;The end is\
            not the end.\n&#34;);

    return 0;
}
</code></pre><p>结果是:</p>
<pre tabindex="0"><code>The end is            not the end.
</code></pre><h3 id="小总结">小总结</h3>
<ol>
<li><strong>字符串是一种数组</strong></li>
<li>不能直接参与运算</li>
<li>一般用数组遍历的方式使用字符串</li>
<li>唯一特殊的是可以用字符串字面量直接对字符数组初始化</li>
</ol>
<h2 id="字符串常量-1">字符串常量</h2>
<p>尝试对一个直接定义的字符串做修改</p>
<pre tabindex="0"><code>char *s=&#34;Hao&#34;;
s[0]=&#39;C&#39;;
</code></pre><p>结果是程序崩溃</p>
<blockquote>
<p>实际上, 通过查询变量的地址, 不难发现<br>
这些字符串字面量的实际地址很小(相较于其他变量的地址)<br>
其实这个地址指向的是存放原始代码的地方, 收到系统保护, 显然是不允许修改的</p>
</blockquote>
<p>这是因为 <strong>字符串常量</strong> 存储的位置与其他变量不同<br>
其实质是一个只读变量<br>
相当于<code>const char *s</code></p>
<h3 id="采用数组">采用数组</h3>
<pre tabindex="0"><code>char s[]=&#34;Hao&#34;;
s[0]=&#39;C&#39;;
</code></pre><p>这种方法就不会报错了</p>
<blockquote>
<p>还是通过查看地址就能发现<br>
此时的地址较大, 说明是一般的变量了</p>
</blockquote>
<h3 id="指针和数组的选择">指针和数组的选择</h3>
<p>选用数组:</p>
<ul>
<li>表示 &ldquo;字符串就在这儿&rdquo;</li>
<li>作为本地变量, 空间被自动开辟/回收</li>
</ul>
<p>选用指针:</p>
<ul>
<li>不知道在哪里, 只是去读取不做修改</li>
<li>要动态分配空间的话(使用<em><strong>malloc</strong></em>), 必定需要使用指针</li>
</ul>
<p>此外, 作为一个函数的参数时, 这两种效果一致</p>
<blockquote>
<p>要构造字符串, 选用数组<br>
要处理字符串, 选用指针</p>
</blockquote>
<h2 id="字符串的有关操作">字符串的有关操作</h2>
<h3 id="赋值">赋值</h3>
<pre tabindex="0"><code>char* s1 = &#34;title&#34;;
char* s2;
s2=s1;
</code></pre><p>根据之前的内容我们可以知道, 第三行的赋值命令的实质, 只是让指针<code>s2</code>也指向了<code>s1</code>指向的字符串的地址<br>
这个过程并不会开辟新的空间, 创造新的字符串</p>
<blockquote>
<p>之后在字符串函数中, 有个<em><strong>strcpy</strong></em>函数可以实现创造一个新的一样的字符串的需求</p>
</blockquote>
<h3 id="输入输出">输入输出</h3>
<pre tabindex="0"><code>char string[8];
scanf(&#34;%s&#34;, string);
printf(&#34;%s&#34;, string);
</code></pre><p>字符串对应的 <strong>格式字符</strong> 是<code>&quot;%s&quot;</code></p>
<h4 id="读取的机制">读取的机制</h4>
<p>对于<em><strong>scanf</strong></em>, 其实际动作是读取到 <strong>空格/换行符/Tab</strong> 为止<br>
这个读取到的&quot;单词&quot;是不包含上述的三样的<br>
而且<em><strong>scanf</strong></em>是不安全的, 因为ta不知道读取内容的长度</p>
<pre tabindex="0"><code>char word1[8];
char word2[8];
scanf(&#34;%s&#34;, word1);
scanf(&#34;%s&#34;, word2);
printf(&#34;%s|&lt;=\n&#34;, word1);
printf(&#34;%s|&lt;=\n&#34;, word2);
</code></pre><p>输入的内容是: <code>hello world[回车]</code><br>
输出的内容是:</p>
<pre tabindex="0"><code>hello|&lt;=
world|&lt;=
</code></pre><h4 id="安全的输入">安全的输入</h4>
<p>可以在格式字符中间加入一个限定, 指定读入的字符个数</p>
<pre tabindex="0"><code>char string[8];
scanf(&#34;%7s&#34;, string);
</code></pre><p>下一个<em><strong>scanf</strong></em>的读取这后面开始</p>
<blockquote>
<p>注意数字应当等于字符串数组的大小<strong>减一</strong></p>
</blockquote>
<blockquote>
<p><em><strong>scanf</strong></em>非常不安全, 如果纵容ta随意读取的话, 会造成 <strong>数据溢出</strong><br>
其后果可能报错, 可能无大碍, 可能崩溃<br>
更严重的是, 通过ta, 攻击者可以注入攻击性代码, 篡改内存, 甚至能实现操纵电脑</p>
</blockquote>
<h4 id="常见错误">常见错误</h4>
<pre tabindex="0"><code>char *string;
scanf(&#34;%s&#34;, string);
</code></pre><p>第一行代码的意义是: 定义一个字符串类型的指针, 但违背初始化, 是个 <strong>野指针</strong></p>
<blockquote>
<p>这种定义通俗来说就是:&quot;<em><strong>string</strong></em>是一个将来要指向某个字符数组的指针&quot;<br>
未被初始化就意味着ta会指向任何地方, 有可能会指向不该指的地方</p>
</blockquote>
<h4 id="空字符串">空字符串</h4>
<p><code>char a1[100]=&quot;&quot;;</code><br>
这行代码初始化了一个空字符串</p>
<ul>
<li>这是正确的操作, <code>a1</code>是合法的字符串</li>
<li><code>a1[0]=='\0'</code>是<code>true</code></li>
</ul>
<p><code>char a2[]=&quot;&quot;;</code>
如果让电脑自动分配空间, 那么<code>a2</code>的长度就是1<br>
并且唯一的元素<code>a2[0]</code>就是<code>'\0'</code>, 没有意义, 无法存放字符串</p>
<h2 id="字符串数组">字符串数组</h2>
<h3 id="一些表达方式">一些表达方式</h3>
<ul>
<li><code>char **a;</code>: <code>a</code>是一个指针, 指向另一个指针, 而那个指针指向一个字符(串)</li>
</ul>
<blockquote>
<p>这样的指针通常称为 <em>二级指针</em></p>
</blockquote>
<ul>
<li><code>char b[][]</code>: 编译无法通过, 因为第二位的大小必须给定</li>
<li><code>char c[][10]</code>: 表示若干个大小为10的字符数组, 但是如果用于储存字符串, 那么其长度必须确定有上界</li>
<li><code>char *d[]</code>: 每一个元素都是一个字符指针, 能装下很多字符串. 因此, 一般用ta作为字符串数组</li>
</ul>
<h3 id="程序参数">程序参数</h3>
<p>来看看<em><strong>main</strong></em>函数的参数:<br>
<code>int main (int argc, char const *argv[])</code></p>
<ul>
<li><code>argc</code>: 表示字符串数组的个数</li>
<li><code>*argv[]</code>: 字符串数组, 存有若干指令, 这些指令是在运行程序时一并输入的参数</li>
</ul>
<p>做一个很简单的试验就能知道<code>*argv[]</code>存了什么</p>
<pre tabindex="0"><code>int main(int argc, char const *argv[])
{
    for (int i = 0; i &lt; argc; i++)
    {
        printf(&#34;%d: %s\n&#34;, i, argv[i]);
    }

    return 0;
}
</code></pre><p>编译为<em><strong>exe</strong></em>文件后在命令行输入指令: <code>.\test.exe 123 abc \n \t</code><br>
会发现输出结果为:</p>
<pre tabindex="0"><code>0: [文件目录]\test.exe
1: 123
2: abc
3: \n
4: \t
</code></pre><blockquote>
<p>第[0]条的意义是什么?<br>
有时候可以说明是以何种方式来运行程序的(比如这种方式下就得到了文件的目录)</p>
</blockquote>
<blockquote>
<p>通过这种方式可以在外部给程序传参了</p>
</blockquote>
<h2 id="字符函数">字符函数</h2>
<h3 id="单个字符输入-putchar">单个字符输入 putchar</h3>
<h4 id="语法">语法</h4>
<p><strong>原型</strong><br>
<code>int putchar(int c);</code><br>
<strong>使用</strong><br>
<code>putchar('a')</code></p>
<h4 id="说明">说明</h4>
<ul>
<li>作用是向 <em>标准输出</em> 写<strong>一个</strong>字符</li>
<li>接受的参数是<em><strong>int</strong></em>类型, 但实际上只能接收一个字符的大小</li>
<li>返回值是写了几个字符(通常是<code>1</code>)</li>
<li>如果写入失败, 返回<em><strong>EOF</strong></em> (<em>end of file</em>)</li>
</ul>
<blockquote>
<p><em><strong>EOF</strong></em>是C语言中定义的 <em><strong>&ldquo;宏&rdquo;</strong></em>, 其<strong>值</strong>是<code>-1</code></p>
</blockquote>
<h3 id="单个字符输出-getchar">单个字符输出 getchar</h3>
<h4 id="语法-1">语法</h4>
<p><strong>原型</strong><br>
<code>int getchar(void);</code><br>
<strong>使用</strong><br>
<code>char a = getchar()</code></p>
<h4 id="说明-1">说明</h4>
<ul>
<li>之所以返回值是<em><strong>int</strong></em>, 是因为有可能要返回<em><strong>EOF</strong></em></li>
</ul>
<h2 id="字符串函数">字符串函数</h2>
<h3 id="所用的库">所用的库</h3>
<p>常用的标准库是<code>&lt;string.h&gt;</code><br>
常用的字符串函数有:</p>
<ul>
<li><code>strlen</code></li>
<li><code>strcmp</code></li>
<li><code>strcpy</code></li>
<li><code>strcat</code></li>
<li><code>strchr</code></li>
<li><code>strstr</code></li>
</ul>
<h3 id="strlen">strlen</h3>
<p><strong>原型</strong>: <code>size_t strlen(const char *s);</code><br>
<strong>作用</strong>: 返回<code>s</code>的字符串的长度(<strong>不包括末尾的0</strong>)<br>
<strong>备注</strong>: <strong>len</strong> 是 <strong>length</strong> 的缩写</p>
<p>可能的实现形式:</p>
<pre tabindex="0"><code>int mylen(const char* s){
    int index = 0;
    while (s[index++]!=&#39;\0&#39;)
        ;
    return --index;
}
</code></pre><h3 id="strcmp">strcmp</h3>
<p><strong>原型</strong>: <code>int strcmp(const char *s1, const char *s2);</code><br>
<strong>作用</strong>: 比较两个字符串是否相等<br>
<strong>返回值</strong>:</p>
<ul>
<li><code>0</code>: 表示两者相等</li>
<li>大于零: 表示前者<strong>大于</strong>后者</li>
<li>小于零: 表示前者<strong>小于</strong>后者</li>
</ul>
<blockquote>
<p>这里的大小是说<strong>字母的ASCII码值</strong>, 字母<code>'a'</code>就比<code>'b'</code>来的小<br>
返回值其实就是: <strong>第一个不相等的位置上的字符的差值</strong></p>
</blockquote>
<p>备注: <strong>cmp</strong> 是 <strong>compare</strong> 的缩写</p>
<p>可能的实现形式:</p>
<ul>
<li>数组形式</li>
</ul>
<pre tabindex="0"><code>int mycmp(const char *s1, const char *s2)
{
    int i = 0;
    while (s1[i] == s2[i] &amp;&amp; s1[i] != &#39;\0&#39;)
    {
        i++;
    }
    return s1[i] - s2[i];
}
</code></pre><ul>
<li>指针形式</li>
</ul>
<pre tabindex="0"><code>int mycmp(const char *s1, const char *s2)
{
    while (*s1 == *s2 &amp;&amp; *s1 != &#39;\0&#39;)
    {
        s1++;
        s2++;
    }
    return *s1 - *s2;
}
</code></pre><blockquote>
<p>如果直接<code>s1==s2</code>会得到什么?<br>
<strong>永远</strong>会是<code>false</code>和<em><strong>warning</strong></em>!<br>
因为这个操作实质上是在比较两者的地址, 而地址绝对不是同一个</p>
</blockquote>
<blockquote>
<p>有一些编译器的<em><strong>strcmp</strong></em>只会返回<code>0</code>或者<code>±1</code><br>
那这个时候返回值可以改写为三元表达式, 能达到相同效果</p>
</blockquote>
<h3 id="strcpy">strcpy</h3>
<p><strong>原型</strong>: <code>char* strcpy(char *restrict dst, const char *restrict src);</code></p>
<blockquote>
<p>关键字: <em><strong>restrict</strong></em>表明<code>src</code>和<code>dst</code>不能<strong>重叠</strong></p>
<blockquote>
<p><strong>&ldquo;重叠&rdquo;</strong> 就是说<code>dst</code>可能就在<code>src</code>的前方, &ldquo;拷贝&quot;的动作会覆盖原字符</p>
</blockquote>
</blockquote>
<p><strong>作用</strong>: 把<code>src</code>的字符拷贝到<code>dst</code><br>
<strong>返回值</strong>: 就是<code>dst</code><br>
<strong>注意</strong>: 参数先<code>dst</code>后<code>src</code></p>
<h4 id="复制一个字符串">复制一个字符串</h4>
<pre tabindex="0"><code>char *dst = (char *)malloc(strlen(src) + 1);
strcpy(dst, src);
</code></pre><p>一个小套路, 先申请动态分配空间, 确保这里的<code>dst</code>不会涉及其他内存, 是独立的存在<br>
<strong>注意</strong>: 别漏了<code>+1</code></p>
<h4 id="可能的实现形式">可能的实现形式</h4>
<ul>
<li>数组</li>
</ul>
<pre tabindex="0"><code>char* mycpy(char *dst, const char *src)
{
    int index = 0;
    while (src[index]!=&#39;\0&#39;)
    {
        dst[index] = src[index];
        index++;
    }
    dst[index] = &#39;\0&#39;;
    return dst;
}
</code></pre><ul>
<li>指针</li>
</ul>
<pre tabindex="0"><code>char* mycpy(char *dst, const char *src)
{
    char *result = dst;
    while (*dst++=*src++)
        ;
    return result;
}
</code></pre><blockquote>
<p>事实上, 无论代码怎么精简, 编译之后效率是一样的<br>
写的很精简只会令人难以理解(可以看做是一种另类的锻炼方式吧)</p>
</blockquote>
<h3 id="strcat">strcat</h3>
<p><strong>原型</strong>: <code>char* strcat(char *restrict s1, const char *restrict s2);</code><br>
<strong>作用</strong>: 吧<code>s2</code>拷贝到<code>s1</code>后面, 接成更长的字符串</p>
<blockquote>
<p>实质还是一种拷贝<br>
其实就是把<code>s2</code>的第一个字符拷贝到<code>s1</code>最后的<code>\0</code></p>
</blockquote>
<p><strong>返回值</strong>: <code>s1</code></p>
<h4 id="安全问题">安全问题</h4>
<p><code>strcpy</code>与<code>strcat</code>都存在明显的安全隐患<br>
即, <strong>盲目的写入</strong><br>
这很可能会覆盖掉其他需要的数据</p>
<h4 id="安全的版本">安全的版本</h4>
<ul>
<li>
<p>对于<em><strong>cpy</strong></em><br>
<code>char* strncpy(char *restrict dst, const char *restrict src, size_t n);</code></p>
</li>
<li>
<p>对于<em><strong>cat</strong></em><br>
<code>char* strncat(char *restrict s1, const char *restrict s2, size_t n);</code></p>
</li>
</ul>
<p>上述两个函数多了一个参数<code>n</code><br>
<code>n</code>表示 <strong>目的地最多能容纳多少字符</strong><br>
如果超出了这个值, 多余的会被掐掉<br>
因此不存在越界问题</p>
<ul>
<li>对于<em><strong>cmp</strong></em><br>
<code>int strncmp(const char *s1, const char *s2, size_t n);</code></li>
</ul>
<p>这里其实并非是出于&quot;安全&quot;目的而设计这个函数<br>
这个<code>n</code>表示仅仅比较两个字符串的前<code>n</code>位, 其余忽略</p>
<h3 id="strchr">strchr</h3>
<p><strong>原型</strong>:</p>
<ul>
<li><code>char * strchr(const char *s, int c);</code></li>
<li><code>char * strrchr(const char *s, int c);</code></li>
</ul>
<p><strong>作用</strong>: 在字符串<code>s</code>中寻找字符<br>
后者只是在名字上多了一个&rsquo;r&rsquo;, 表示从右边开始找</p>
<p><strong>返回值</strong>:<br>
返回那个字符的指针<br>
没有找到返回 <em><strong>null</strong></em></p>
<h4 id="寻找第二个字符">寻找第二个字符</h4>
<pre tabindex="0"><code>char str[] = &#34;zhyDaDa&#34;;
char *p = strchr(str, &#39;D&#39;);
p = strchr(p + 1, &#39;D&#39;);
printf(&#34;%s\n&#34;, p);
</code></pre><p>这里当找到第一个&rsquo;D&rsquo;后得到了其指针<code>p</code>,<br>
此时的<code>p</code>可以看做是一个字符串(因为后面有<code>'\0'</code>)<br>
从<code>p</code>的后面一个字符找起, 即得到第二个&rsquo;D'</p>
<h4 id="得到第一个配对之前的字符串">得到第一个配对之前的字符串</h4>
<pre tabindex="0"><code>char str[] = &#34;zhyDaDa&#34;;
char *p = strchr(str, &#39;D&#39;);
char *t = (char *)malloc(strlen(str) + 1);
char c = *p;
*p = &#39;\0&#39;;
strcpy(t, str);
*p = c;
printf(&#34;str: %s\n&#34;, str);
printf(&#34;p: %s\n&#34;, p);
printf(&#34;t: %s\n&#34;, t);
printf(&#34;c: %c\n&#34;, c);
free(t);
</code></pre><p>输出的结果是:</p>
<pre tabindex="0"><code>str: zhyDaDa
p: DaDa
t: zhy
c: D
</code></pre><p>这里用了一个非常巧妙的小技巧<br>
即, 将扫描到的第一个匹配改写成<code>'\0'</code><br>
这样原来的字符串就缩减到了第一个匹配之前的字符串<br>
当然这之后还要改回去, <code>c</code>就是临时储存的被改掉的字符</p>
<h3 id="strstr">strstr</h3>
<p><strong>原型</strong>:</p>
<ul>
<li><code>char * strstr(const caht *s1, const char *s2);</code></li>
<li><code>char * strcasestr(const caht *s1, const char *s2);</code></li>
</ul>
<p><strong>作用</strong>: 前者在一个字符串中寻找字符串<br>
后者的区别是, 在名称上多了一个&quot;case&rdquo;<br>
ta在寻找字符串的时候会 <strong>忽略大小写</strong></p>
<h2 id="关于输入输出-和-shell的一些知识">关于输入输出 和 SHELL的一些知识</h2>
<h3 id="什么是shell">什么是SHELL?</h3>
<p>SHELL就是人机交互的接口<br>
用户敲键盘, 输入的字符, 输入快捷键等等行为, 会先送到SHELL去处理<br>
SHELL会准备一个 <strong>缓存区</strong> 去接受用户的输入<br>
在那之后SHELL把这个缓存区交给程序去处理<br>
程序再告诉SHELL要显示什么, 藉由SHELL来打印到控制台</p>
<blockquote>
<p>通俗来说, SHELL 是连接用户和程序之间的一个<strong>中介</strong></p>
</blockquote>
<h3 id="为什么敲回车程序才继续">为什么敲回车程序才继续?</h3>
<blockquote>
<p>既然<em><strong>getchar</strong></em>只接收一个字符, 为什么在用户输入了很多内容后仍旧处在&quot;等待输入&quot;的状态, 直到用户键入回车才有反应?</p>
</blockquote>
<p>这是因为SHELL最基本的一个功能就是 <strong>&ldquo;行编辑&rdquo;</strong><br>
在<strong>按下回车之前</strong>, 他们都没有被送到程序那里去</p>
<blockquote>
<p>&ldquo;行编辑&quot;其实就是在输入前的一个调整, 让你写下来的东西处在编辑状态<br>
否则如果没有这个功能, 你每次按下一个键就会立刻生效, 那么就无法输入大于一个字符的信息了</p>
</blockquote>
<p>当用户编辑好要输入的内容后, 按下了回车<br>
回车的动作被SHELL接收, ta就把用户输入的内容(连带着那个回车一起)并入缓存区<br>
接着SHELL把缓存区的内容交给程序, 此时程序<strong>才从缓存区读入字符</strong><br>
程序一旦读完了缓存区的内容并且又需要用户输入了<br>
那么程序告诉SHELL, SHELL就让用户输入(这就是等待输入的状态)</p>
<blockquote>
<p>比方用户输入的是: <code>abc123</code>并按下回车<br>
那么缓存区的状态就类似于: <code>|a|b|c|1|2|3|\n|\0|</code></p>
<blockquote>
<p>这里的两个<code>|</code>表示一个字符的单位<br>
最后的<code>\0</code>是假想的, 实际中会用其他符号来代替, 用来表示<strong>缓存区的结尾</strong></p>
</blockquote>
<p>如果此时有形如<code>scanf(&quot;%c%c%c%d%d&quot;)</code>的输入命令, 缓存内容不够了<br>
用户再输入: &lsquo;789def<code>并按下回车   那么缓存区就类似于: </code>|a|b|c|1|2|3|\n|7|8|9|d|e|f|\n|\0|`</p>
<blockquote>
<p>如果上述的读取运行了, 那么缓存区就会变成:<br>
<code>|d|e|f|\n|\0|</code><br>
注意, <strong>此时的缓存区不是空的</strong>!<br>
这就是为什么后面跟着的读取会不再要求用户输入!<br>
例如后面还有<em><strong>getchar</strong></em></p>
</blockquote>
<p>这也就是为什么推荐在要求用户输入内容后<br>
最好跟上一个<code>fflush(stdin)</code>来清空缓存</p>
<blockquote>
<p>子函数要求输入后如果有残余的缓存, 那么主函数的输入很可能出问题</p>
</blockquote>
</blockquote>
<h3 id="如何停止输入">如何停止输入?</h3>
<blockquote>
<p>下面这段代码会不断接受并打印输入的内容<br>
只是通过输入字符是无法跳出循环的</p>
</blockquote>
<pre tabindex="0"><code>int c;
while ((c = getchar())!=EOF)
{
    putchar(c);
}
printf(&#34;读到了EOF, 程序正常结束&#34;);
</code></pre><p>此时就要告诉SHELL, 通过SHELL达成目的</p>
<p>如果键入<code>Control+C</code>, 那么相当于要求SHELL强制结束程序<br>
此时由于程序非正常退出, 最后一行代码就不会输出</p>
<p>如果键入<code>Contorl+Z</code>(不同的SHELL如Linux的, 就是输入<code>Contorl+D</code>)<br>
此时SHELL就会在缓存区的最后添上代表<em><strong>EOF</strong></em>的一个符号<br>
此时 <em><strong>getchar</strong></em> 才读到了 <em><strong>EOF</strong></em><br>
最后的输出也证实了这一点</p>
]]></content>
		</item>
		
		<item>
			<title>L8_指针___2022-12-03</title>
			<link>https://zhydada.github.io/posts/l8_%E6%8C%87%E9%92%88___2022-12-03/</link>
			<pubDate>Sat, 03 Dec 2022 20:46:02 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l8_%E6%8C%87%E9%92%88___2022-12-03/</guid>
			<description>* 对应课程: ~ 目录 指针 指针的定义 重要的小细节 作为参数的指针 取地址 取地址运算符 无法取地址的情况 有趣试验 相邻的变量 数组的地址 二维数组的地址 应用 应</description>
			<content type="html"><![CDATA[<p>* 对应课程:  ~ <br>
目录</p>
<ul>
<li><a href="#%E6%8C%87%E9%92%88">指针</a>
<ul>
<li><a href="#%E6%8C%87%E9%92%88%E7%9A%84%E5%AE%9A%E4%B9%89">指针的定义</a></li>
<li><a href="#%E9%87%8D%E8%A6%81%E7%9A%84%E5%B0%8F%E7%BB%86%E8%8A%82">重要的小细节</a></li>
<li><a href="#%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0%E7%9A%84%E6%8C%87%E9%92%88">作为参数的指针</a></li>
</ul>
</li>
<li><a href="#%E5%8F%96%E5%9C%B0%E5%9D%80">取地址</a>
<ul>
<li><a href="#%E5%8F%96%E5%9C%B0%E5%9D%80%E8%BF%90%E7%AE%97%E7%AC%A6">取地址运算符</a></li>
<li><a href="#%E6%97%A0%E6%B3%95%E5%8F%96%E5%9C%B0%E5%9D%80%E7%9A%84%E6%83%85%E5%86%B5">无法取地址的情况</a></li>
<li><a href="#%E6%9C%89%E8%B6%A3%E8%AF%95%E9%AA%8C">有趣试验</a>
<ul>
<li><a href="#%E7%9B%B8%E9%82%BB%E7%9A%84%E5%8F%98%E9%87%8F">相邻的变量</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E5%9C%B0%E5%9D%80">数组的地址</a></li>
<li><a href="#%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E7%9A%84%E5%9C%B0%E5%9D%80">二维数组的地址</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%BA%94%E7%94%A8">应用</a>
<ul>
<li><a href="#%E5%BA%94%E7%94%A8%E4%B8%80_%E4%BA%A4%E6%8D%A2%E5%8F%98%E9%87%8F">应用一_交换变量</a></li>
<li><a href="#%E5%BA%94%E7%94%A8%E4%BA%8C_%E5%A4%9A%E4%B8%AA%E8%BF%94%E5%9B%9E%E5%80%BC">应用二_多个返回值</a></li>
<li><a href="#%E5%BA%94%E7%94%A8%E4%B8%89_%E8%BF%90%E7%AE%97%E7%8A%B6%E6%80%81">应用三_运算状态</a></li>
<li><a href="#%E5%B8%B8%E8%A7%81%E8%AF%AF%E5%8C%BA">常见误区</a></li>
</ul>
</li>
<li><a href="#%E6%8C%87%E9%92%88%E4%B8%8E%E6%95%B0%E7%BB%84">指针与数组</a>
<ul>
<li><a href="#%E5%8F%82%E6%95%B0%E8%A1%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E7%BB%84">参数表中的数组</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E5%8F%98%E9%87%8F%E6%98%AF%E7%89%B9%E6%AE%8A%E7%9A%84%E6%8C%87%E9%92%88">数组变量是特殊的指针</a></li>
</ul>
</li>
<li><a href="#%E6%8C%87%E9%92%88%E4%B8%8Econst">指针与const</a>
<ul>
<li><a href="#%E6%8C%87%E9%92%88%E6%98%AFconst">指针是const</a></li>
<li><a href="#%E6%89%80%E6%8C%87%E6%98%AFconst">所指是const</a></li>
<li><a href="#%E5%B0%8F%E7%BB%83%E4%B9%A0">小练习</a></li>
<li><a href="#%E8%BD%AC%E6%8D%A2">转换</a></li>
<li><a href="#const%E6%95%B0%E7%BB%84">const数组</a></li>
<li><a href="#%E4%BF%9D%E6%8A%A4%E6%95%B0%E7%BB%84%E5%80%BC">保护数组值</a></li>
</ul>
</li>
<li><a href="#%E6%8C%87%E9%92%88%E7%9A%84%E8%BF%90%E7%AE%97">指针的运算</a>
<ul>
<li><a href="#%E5%8A%A0%E4%B8%80%E7%9A%84%E5%AE%9E%E8%B4%A8">加一的实质</a></li>
<li><a href="#%E5%8F%AF%E8%83%BD%E5%8F%82%E4%B8%8E%E7%9A%84%E8%AE%A1%E7%AE%97">可能参与的计算</a></li>
<li><a href="#%E8%BF%9E%E6%8B%9B">连招</a></li>
<li><a href="#0%E5%9C%B0%E5%9D%80">0地址</a></li>
</ul>
</li>
<li><a href="#%E6%8C%87%E9%92%88%E7%9A%84%E7%B1%BB%E5%9E%8B">指针的类型</a>
<ul>
<li><a href="#%E6%9C%AA%E7%9F%A5%E7%B1%BB%E5%9E%8B">未知类型</a></li>
<li><a href="#%E6%8C%87%E9%92%88%E7%9A%84%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">指针的类型转换</a></li>
</ul>
</li>
<li><a href="#%E5%8A%A8%E6%80%81%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D">动态内存分配</a>
<ul>
<li><a href="#%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE">接收数据</a></li>
<li><a href="#%E6%B2%A1%E7%A9%BA%E9%97%B4%E7%9A%84%E6%83%85%E5%86%B5">没空间的情况</a></li>
<li><a href="#%E7%AE%97%E7%AE%97%E8%A2%AB%E5%88%86%E9%85%8D%E5%A4%9A%E5%B0%91%E7%A9%BA%E9%97%B4">算算被分配多少空间</a></li>
<li><a href="#free%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">free的注意事项</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="指针">指针</h2>
<p><strong>指针</strong>就是<strong>保存地址的变量</strong></p>
<h3 id="指针的定义">指针的定义</h3>
<pre tabindex="0"><code>int i;
int* p = &amp;i;
</code></pre><p>上面这段的含义是:</p>
<ul>
<li><code>i</code>的地址交给了<code>p</code></li>
<li><code>p</code>获得的值是<code>i</code>的地址</li>
<li><code>p</code>指向了<code>i</code></li>
</ul>
<p>这几种说法都正确</p>
<h3 id="重要的小细节">重要的小细节</h3>
<pre tabindex="0"><code>int* p,q;  
int *p,q;
</code></pre><p>这里的<code>*</code>是附着于<code>p</code>身上的, 与ta靠近的位置无关<br>
<strong>注意</strong>: 不存在<code>int*</code>这种变量类型!<br>
<strong>正确的说法</strong>是: <code>*p</code>是一个<em><strong>int</strong></em> 类型的变量, 于是<code>p</code>是一个 <em>指针</em></p>
<h3 id="作为参数的指针">作为参数的指针</h3>
<p><code>void f(int *p)</code><br>
通过传递指针, 函数得到了参数的地址<br>
这使得函数内部拥有了<strong>访问外部</strong>的能力</p>
<blockquote>
<p>所谓 <em>访问</em> 就是可以对变量进行<strong>读写</strong></p>
</blockquote>
<blockquote>
<p>满分解释: <strong>把你家的门牌号扒下来给物管</strong></p>
</blockquote>
<h2 id="取地址">取地址</h2>
<h3 id="取地址运算符">取地址运算符</h3>
<p><code>&amp;</code>是<strong>取地址运算符</strong>, 也是一个运算符<br>
作用是取得<strong>变量的地址</strong>, 其后必须是一个变量<br>
取得的地址输出时要使用<code>%p</code><br>
地址的(数据)大小与int是否相同<strong>取决于编译器</strong><br>
<strong>地址与整数不一定是相同的</strong></p>
<h3 id="无法取地址的情况">无法取地址的情况</h3>
<p><code>int p = (int)(i++);</code> 会报出<em><strong>error</strong></em><br>
因为, <code>&amp;</code>后面 <strong>必须是明确的一个变量</strong></p>
<h3 id="有趣试验">有趣试验</h3>
<h4 id="相邻的变量">相邻的变量</h4>
<pre tabindex="0"><code>int main()
{
    int i=0;
    int p = (int)&amp;i;
    printf(&#34;%p\n&#34;, &amp;i);
    printf(&#34;%p\n&#34;, &amp;p);
    return 0;
}
</code></pre><p>输出结果为:</p>
<pre tabindex="0"><code>000000000061FE1C
000000000061FE18
</code></pre><blockquote>
<p>在内存中, 先定义的变量在更高的地方<br>
在C语言的内存模型中
本地变量被分配在一个被称为 <strong>堆栈(stack)</strong> 的地方<br>
堆栈会自上而下分配变量</p>
</blockquote>
<blockquote>
<p>在这个例子中, 两个 <em><strong>int</strong></em> 是紧挨着定义的<br>
因此相差<code>4</code></p>
</blockquote>
<h4 id="数组的地址">数组的地址</h4>
<pre tabindex="0"><code>int main()
{
    int a[10]={0};
    
    printf(&#34;%p\n&#34;, a);
    printf(&#34;%p\n&#34;, &amp;a);
    printf(&#34;%p\n&#34;, &amp;a[0]);
    printf(&#34;%p\n&#34;, &amp;a[1]);

    return 0;
}
</code></pre><p>结果是:</p>
<pre tabindex="0"><code>000000000061FDF0
000000000061FDF0
000000000061FDF0
000000000061FDF4
</code></pre><blockquote>
<p>数组在堆栈中从下而上分配<br>
数组的名字就是一个地址<br>
其与第0个元素的地址一致</p>
</blockquote>
<h4 id="二维数组的地址">二维数组的地址</h4>
<pre tabindex="0"><code>    int a[10][3];
    
    printf(&#34;a: %p\n&#34;, a);
    printf(&#34;&amp;a: %p\n&#34;, &amp;a);
    printf(&#34;&amp;a[0]: %p\n&#34;, &amp;a[0]);
    printf(&#34;&amp;a[1]: %p\n&#34;, &amp;a[1]);
    printf(&#34;&amp;a[0][0]: %p\n&#34;, &amp;a[0][0]);
    printf(&#34;&amp;a[1][0]: %p\n&#34;, &amp;a[1][0]);
    printf(&#34;&amp;a[1][2]: %p\n&#34;, &amp;a[1][2]);
</code></pre><p>其结果:</p>
<pre tabindex="0"><code>a: 000000000061FDA0
&amp;a: 000000000061FDA0
&amp;a[0]: 000000000061FDA0
&amp;a[1]: 000000000061FDAC
&amp;a[0][0]: 000000000061FDA0
&amp;a[1][0]: 000000000061FDAC
&amp;a[1][2]: 000000000061FDB4
</code></pre><p>为了让结果更具可读性, 稍微改了一下</p>
<pre tabindex="0"><code>    int a[10][3];

    printf(&#34;a: %d\n&#34;, (int)(a) - (int)a);
    printf(&#34;&amp;a: %d\n&#34;, (int)(&amp;a) - (int)a);
    printf(&#34;&amp;a[0]: %d\n&#34;, (int)(&amp;a[0]) - (int)a);
    printf(&#34;&amp;a[1]: %d\n&#34;, (int)(&amp;a[1]) - (int)a);
    printf(&#34;a[0]: %d\n&#34;, (int)(a[0]) - (int)a);
    printf(&#34;a[1]: %d\n&#34;, (int)(a[1]) - (int)a);
    printf(&#34;&amp;a[0][0]: %d\n&#34;, (int)(&amp;a[0][0]) - (int)a);
    printf(&#34;&amp;a[0][1]: %d\n&#34;, (int)(&amp;a[0][1]) - (int)a);
    printf(&#34;&amp;a[0][2]: %d\n&#34;, (int)(&amp;a[0][2]) - (int)a);
    printf(&#34;&amp;a[1][0]: %d\n&#34;, (int)(&amp;a[1][0]) - (int)a);
    printf(&#34;&amp;a[1][1]: %d\n&#34;, (int)(&amp;a[1][1]) - (int)a);
    printf(&#34;&amp;a[1][2]: %d\n&#34;, (int)(&amp;a[1][2]) - (int)a);
</code></pre><p>结果是:</p>
<pre tabindex="0"><code>a: 0
&amp;a: 0
&amp;a[0]: 0
&amp;a[1]: 12
a[0]: 0
a[1]: 12
&amp;a[0][0]: 0
&amp;a[0][1]: 4
&amp;a[0][2]: 8
&amp;a[1][0]: 12
&amp;a[1][1]: 16
&amp;a[1][2]: 20
</code></pre><p>总结得出:</p>
<ul>
<li>数组名称对应着<code>a[0][0]</code>的地址</li>
<li>往后的所有元素都越来越大(在堆栈中向上堆叠)</li>
<li>每一行的最后一个元素与下一行的第一个元素紧挨着</li>
</ul>
<h2 id="应用">应用</h2>
<h3 id="应用一_交换变量">应用一_交换变量</h3>
<pre tabindex="0"><code>void swap(int *pa, int *pb);

int main()
{
    int a = 4, b = 6;
    swap(&amp;a, &amp;b);
    printf(&#34;a=%d, b=%d\n&#34;, a, b);

    return 0;
}

void swap(int *pa, int *pb)
{
    int t = *pa;
    *pa = *pb;
    *pb = t;
}
</code></pre><p>遇到<em><strong>swap</strong></em>这种对外部参数的值操作的函数, 只能使用指针</p>
<h3 id="应用二_多个返回值">应用二_多个返回值</h3>
<p>传入的参数实际上是一些容器<br>
函数实际上在将多个返回值装入这个容器<br>
这一过程必定需要使用指针</p>
<pre tabindex="0"><code>void MinMax(int a[], int len, int *min, int *max);

int main()
{
    int a[] = {10, 99, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int min,max;
    MinMax(a, sizeof(a) / sizeof(a[0]), &amp;min, &amp;max);
    printf(&#34;min=%d; max=%d\n&#34;, min, max);

    return 0;
}

void MinMax(int a[], int len, int *min, int *max){
    *min = *max = a[0];
    for (int i = 0; i &lt; len; i++)
    {
        if(a[i]&lt;*min){
            *min = a[i];
        }
        if(a[i]&gt;*max){
            *max = a[i];
        }
    }    
}
</code></pre><blockquote>
<p>在这一类场景中, <code>min</code>和<code>max</code>虽然是main函数传入的<strong>参数</strong><br>
但他们的实际作用, 是<strong>把返回值带出来</strong></p>
</blockquote>
<h3 id="应用三_运算状态">应用三_运算状态</h3>
<p>函数操作会有成功与否, 一般(如<em><strong>scanf</strong></em>)会返回<code>0</code>表示成功, <code>-1</code>表示失败<br>
如果函数运算的结果也可能是<code>0</code>或<code>-1</code>那么就无法判断函数是否成功执行<br>
因此, 需要分开返回 <strong>运算状态</strong> 和 运算的<strong>实际结果</strong><br>
一般来说, <strong>函数的返回值</strong>是运算状态, 用另一个<strong>指针参数</strong>带出实际结果</p>
<pre tabindex="0"><code>int divide(int a, int b, int *c);

int main()
{
    int a = 5, b = 2, c;
    if (divide(a, b, &amp;c))
    {
        printf(&#34;%d/%d=%d\n&#34;, a, b, c);
    }
    return 0;
}

int divide(int a, int b, int *c)
{
    int ret = 1;
    if (b == 0)
    {
        ret = 0;
    }
    else
    {
        *c = a / b;
    }
    return ret;
}
</code></pre><h3 id="常见误区">常见误区</h3>
<p><code>int *p=12;</code><br>
这条语句拆开来看是这样的:</p>
<pre tabindex="0"><code>int *p;
*p = 12;
</code></pre><p><strong>注意</strong>: 这类指针俗称 <em>&ldquo;野生指针&rdquo;</em><br>
因为指针没有明确的指向<br>
此时<code>p</code>可能指向内存中的任意位置<br>
此时如果正好指向不可写入的一块区域<br>
那么程序立刻崩溃</p>
<h2 id="指针与数组">指针与数组</h2>
<h3 id="参数表中的数组">参数表中的数组</h3>
<p>在函数的参数表中, 传入的数组实质上是指针<br>
以上文<a href="#%E5%BA%94%E7%94%A8%E4%BA%8C_%E5%A4%9A%E4%B8%AA%E8%BF%94%E5%9B%9E%E5%80%BC">应用二_多个返回值</a>中的函数来分析<br>
<code>void MinMax(int a[], int len, int *min, int *max)</code><br>
这里可以改写成:<br>
<code>void MinMax(int *a, int len, int *min, int *max)</code><br>
对于这种数组指针, 仍旧可以使用数组运算符<code>[]</code>来参与运算</p>
<blockquote>
<p>一定注意, 所谓</p>
<blockquote>
<p><code>*a</code>与<code>a[]</code>等价</p>
</blockquote>
<p>这只是在函数原型的<strong>参数表</strong>中的说法</p>
</blockquote>
<h3 id="数组变量是特殊的指针">数组变量是特殊的指针</h3>
<ul>
<li>数组变量本身表达地址, 无需对其取地址<br>
<code>int a[10]; int *p=a;</code></li>
<li>但是, 对于数组的单个元素, 都表达确切的变量, 需要用<code>&amp;</code>取地址<br>
<code>a==&amp;a[0]</code></li>
<li><code>[]</code>运算符亦可以对指针使用
<code>p[0]</code>与<code>a[0]</code>完全等价</li>
<li><code>*</code>运算符显然也可以对数组使用<br>
<code>*(a+2) = 25</code></li>
</ul>
<blockquote>
<p><code>p[2]</code>的含义是: 将<code>p</code>视作数组的第一个元素的地址, 取其第3个单元<br>
<code>int a[]</code> 同 <code>int * const a=...</code> 等价<br>
这里的<em><strong>const</strong></em>是<strong>常量</strong>的意思, 即数组变量这种特殊的指针一旦被定义就无法再改变其指向的对象了</p>
</blockquote>
<h2 id="指针与const">指针与const</h2>
<p><em><strong>const</strong></em> 是说值不能被修改<br>
指针本身有<em>可能</em>是 <em><strong>const</strong></em> , 指针所指的变量也<em>可能</em>是 <em><strong>const</strong></em></p>
<h3 id="指针是const">指针是const</h3>
<p>这意味着该指针一旦得到某个变量的地址, 不能再指向其他变量<br>
<strong>注意</strong>: 指针所指向的值仍旧可以修改, 因为值不是 <em><strong>const</strong></em></p>
<pre tabindex="0"><code>int i = 0;
int * const q = &amp;i;
*q = 26; //OK
q++;     //ERROR
</code></pre><h3 id="所指是const">所指是const</h3>
<p><code>const int *p = &amp;i;</code><br>
这行代码意味着:</p>
<ul>
<li><code>i</code>可以做修改</li>
<li><code>p</code>可以做修改</li>
<li>唯独<strong>不可以</strong>通过<code>*p</code>去修改<code>i</code></li>
</ul>
<h3 id="小练习">小练习</h3>
<pre tabindex="0"><code>int i;
const int* p1 = &amp;i;
int const* p2 = &amp;i;
int *const p3 = &amp;i;
</code></pre><p>答案是:</p>
<ul>
<li><code>p1</code>: 所指是<em><strong>const</strong></em></li>
<li><code>p2</code>: 所指是<em><strong>const</strong></em></li>
<li><code>p3</code>: 指针是<em><strong>const</strong></em></li>
</ul>
<blockquote>
<p>判断的技巧: <em><strong>const</strong></em> 和 * 的位置<br>
<em><strong>const</strong></em>在前就是所指不能修改<br>
<em><strong>const</strong></em>在后就是指针不能修改</p>
</blockquote>
<h3 id="转换">转换</h3>
<p>总是可以将非 <em><strong>const</strong></em> 的值转化为 <em><strong>const</strong></em><br>
<code>void f(const int* x);</code><br>
可以照常将一个普通的地址传入, <code>f</code>函数将向你保证:<br>
在<code>f</code>中, 不会对这个地址对应的值做修改</p>
<blockquote>
<p>事实上, 这是一个常用的套路<br>
由于传递的值会很大, 自然会用传地址来代替(<em>数组就是这个想法</em>)<br>
为了避免函数修改数值, 就用<em><strong>const</strong></em>来做保证</p>
</blockquote>
<h3 id="const数组">const数组</h3>
<p><code>const int a[]={1,2,3,4,5,6};</code><br>
数组变量在声明时就是一个<em><strong>const</strong></em>指针<br>
如果再加上<em><strong>const</strong></em>, 就表明数组中每个单元全都是<em><strong>const</strong></em><br>
所以, 初始化时 <strong>必须赋值</strong></p>
<h3 id="保护数组值">保护数组值</h3>
<p>为了避免函数修改数组内的值, 可以在函数声明中设置参数<em><strong>const</strong></em></p>
<h2 id="指针的运算">指针的运算</h2>
<h3 id="加一的实质">加一的实质</h3>
<pre tabindex="0"><code>int *p1;
char *p2;
</code></pre><p>打印他们和<code>+1</code>之后的16进制值, 比较其差值:</p>
<ul>
<li><code>p1+1</code>比<code>p1</code>数值上差4</li>
<li><code>p2+1</code>比<code>p2</code>数值上差1</li>
</ul>
<p>对于指针来说, <code>+1</code>的实际含义是 <strong>指向下一个单元</strong><br>
因此, 从数值上来看, 实际给指针加上的 是数据类型的<em><strong>size</strong></em>大小</p>
<blockquote>
<p>如果<code>+1</code>是字面上的含义, 那么指针移动到代表一个<em><strong>int</strong></em>的四个字节的中间<br>
这样做也是没有任何意义的 <br>
同样, 如果指针指向的不是一片<em>连续分配的空间(如数组)</em>,那么这种运算也没有意义</p>
</blockquote>
<h3 id="可能参与的计算">可能参与的计算</h3>
<ul>
<li>加减法</li>
<li>加加和减减</li>
<li>两个指针相减</li>
<li>两个指针比较</li>
</ul>
<blockquote>
<p>这里还需注意: 指针相减的意义是<strong>两个指针间有几个单元</strong><br>
因此, 对于<em><strong>int</strong></em>指针, 数值上相差<code>24</code>, 但结果是<code>6</code></p>
</blockquote>
<blockquote>
<p>数组中, 单元的地址必定是 <strong>线性递增的</strong></p>
</blockquote>
<h3 id="连招">连招</h3>
<p><code>*p++</code><br>
用意是:</p>
<ul>
<li>取出<code>*p</code>, 即指针指向的内容</li>
<li>顺便指针向后移动</li>
</ul>
<blockquote>
<p><code>*</code>的优先级没有<code>++</code>高</p>
</blockquote>
<blockquote>
<p>有些CPU上, 这个连招会被直接翻译成一条指令 <em>(跑得更快)</em></p>
</blockquote>
<h3 id="0地址">0地址</h3>
<p>每个程序跑起来的时候, 系统都会赋予ta一块 <em>&ldquo;虚拟的&rdquo;</em> 内存空间<br>
因此, 每个程序都有所谓的 <em>0地址</em></p>
<p>但这个地址不能<em>碰</em>, 不仅不能更改, 有时还不允许读取<br>
操作ta可能会导致程序崩溃<br>
因此, <em>0地址</em>被赋予了特殊含义:</p>
<ul>
<li>指向<code>0</code>的指针可以看做是无效的指针(函数返回这样的指针就可能意味着操作不能执行)</li>
<li>给指针初始化的时候可以先初始化为<code>0</code>, 表示ta还尚未被使用</li>
</ul>
<p>有个特殊的字面量叫<em><strong>NULL</strong></em>, 就表示<em>0地址</em><br>
部分编译器仅支持<em><strong>NULL</strong></em>, 所以最好使用ta来表示<em>0地址</em></p>
<h2 id="指针的类型">指针的类型</h2>
<p>指针的类型和其指向的数据类型一致<br>
无论什么类型的指针, 他们都是存放地址的, 因此<strong>所有指针大小一致</strong><br>
考虑到上文分析的指针运算的意义, 不同类型的指针之间不可以赋值(主要为了避免用错指针)</p>
<h3 id="未知类型">未知类型</h3>
<p><code>void * </code>这样的类型表示指向的变量类型未知(或者说不用关心)<br>
其在计算方式上和<code>char * </code>相同<br>
但要注意, 这两个类型的指针仍旧不相通</p>
<h3 id="指针的类型转换">指针的类型转换</h3>
<pre tabindex="0"><code>int *p = &amp;i;
void *q = (void *)p;
</code></pre><p>指针可以转换类型<br>
这种转换并不改变其指向的变量的类型(这个例子里<code>i</code>仍旧是<em><strong>int</strong></em>)<br>
这么做仅仅改变了我们透过<code>p</code>看待<code>i</code>的眼光</p>
<h2 id="动态内存分配">动态内存分配</h2>
<h3 id="接收数据">接收数据</h3>
<p>数据接收前需要知道数据的个数, 这是为了在内存中开辟相应的空间</p>
<blockquote>
<p>在C99之前, 需要手动开辟空间<br>
<code>int *a=(int*)malloc(n*sizeof(int));</code></p>
<blockquote>
<p>这里<em><strong>malloc</strong></em>会返回<code>void *</code><br>
意思就是开辟了一块空的没有意义的空间, 然后把地址告诉你</p>
</blockquote>
<p>而且在程序的最后, 还要加上一句<br>
<code>free(a)</code><br>
表示把用好的空间还回去</p>
</blockquote>
<h3 id="没空间的情况">没空间的情况</h3>
<p>申请空间(<em><strong>malloc</strong></em>)失败会得到返回值<em><strong>NULL</strong></em></p>
<h3 id="算算被分配多少空间">算算被分配多少空间</h3>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main()
{
    void *p;
    int count = 0;
    while ((p = malloc(100 * 1024 * 1024)))
    {
        count++;
    }
    printf(&#34;被分配了%d00MB的空间&#34;, count);

    return 0;
}
</code></pre><p>在笔者的电脑上的结果是:<br>
<code>被分配了43500MB的空间</code></p>
<h3 id="free的注意事项">free的注意事项</h3>
<pre tabindex="0"><code>void *p;
int count = 0;
(p = malloc(100 * 1024 * 1024));
p = &amp;count;
free(p);
</code></pre><p>上述代码运行结果就是程序崩溃<br>
一下情况会崩溃:</p>
<ul>
<li>借了不还</li>
<li>还回去的不是借来的地址
<ul>
<li>例如<code>p+1</code></li>
<li>例如<code>(p=&amp;count)</code></li>
</ul>
</li>
<li><em><strong>free</strong></em> 了之后再 <em><strong>free</strong></em></li>
</ul>
<p>对于小程序, 程序结束之后会直接释放所有内存<br>
但对于服务器/大程序, 长时间 <em>申请不free</em> 会导致<strong>内存逐渐下降</strong>, 这会造成严重的后果<br>
<strong>注意</strong>: 唯独<code>free(NULL)</code>不会报错</p>
<blockquote>
<p>很可能是为了让我们养成 对指针初始化就用<em><strong>NULL</strong></em>的习惯</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>L7_数组___2022-11-27</title>
			<link>https://zhydada.github.io/posts/l7_%E6%95%B0%E7%BB%84___2022-11-27/</link>
			<pubDate>Sun, 27 Nov 2022 00:57:41 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l7_%E6%95%B0%E7%BB%84___2022-11-27/</guid>
			<description>目录 定义数组 语法 本质和特征 数组的特点 数组的单元、下标 有效的下标范围 数组的集成初始化 定义 写法注意 集成初始化时的定位 数组操作 数组长度 数组赋值 数组</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E6%95%B0%E7%BB%84">定义数组</a>
<ul>
<li><a href="#%E8%AF%AD%E6%B3%95">语法</a></li>
<li><a href="#%E6%9C%AC%E8%B4%A8%E5%92%8C%E7%89%B9%E5%BE%81">本质和特征</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E7%89%B9%E7%82%B9">数组的特点</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E5%8D%95%E5%85%83%E4%B8%8B%E6%A0%87">数组的单元、下标</a></li>
<li><a href="#%E6%9C%89%E6%95%88%E7%9A%84%E4%B8%8B%E6%A0%87%E8%8C%83%E5%9B%B4">有效的下标范围</a></li>
</ul>
</li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E9%9B%86%E6%88%90%E5%88%9D%E5%A7%8B%E5%8C%96">数组的集成初始化</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89">定义</a></li>
<li><a href="#%E5%86%99%E6%B3%95%E6%B3%A8%E6%84%8F">写法注意</a></li>
<li><a href="#%E9%9B%86%E6%88%90%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%B6%E7%9A%84%E5%AE%9A%E4%BD%8D">集成初始化时的定位</a></li>
</ul>
</li>
<li><a href="#%E6%95%B0%E7%BB%84%E6%93%8D%E4%BD%9C">数组操作</a>
<ul>
<li><a href="#%E6%95%B0%E7%BB%84%E9%95%BF%E5%BA%A6">数组长度</a></li>
<li><a href="#%E6%95%B0%E7%BB%84%E8%B5%8B%E5%80%BC">数组赋值</a></li>
</ul>
</li>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E5%BA%94%E7%94%A8">数组的应用</a>
<ul>
<li><a href="#%E6%90%9C%E7%B4%A2">搜索</a></li>
<li><a href="#%E7%B4%A0%E6%95%B0%E5%88%A4%E6%96%AD">素数判断</a></li>
</ul>
</li>
<li><a href="#%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84">二维数组</a>
<ul>
<li><a href="#%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E6%8E%92%E5%B8%83">内存中的排布</a></li>
<li><a href="#%E9%81%8D%E5%8E%86">遍历</a></li>
<li><a href="#%E5%88%9D%E5%A7%8B%E5%8C%96">初始化</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="定义数组">定义数组</h2>
<h3 id="语法">语法</h3>
<p><strong>语法</strong>: <code>&lt;类型&gt; 变量名称[元素数量]</code></p>
<ul>
<li><strong>类型</strong>是指数组中每个元素的类型</li>
<li><strong>元素数量</strong>必须是整数</li>
<li><strong>元素数量</strong>应当在编译时就是确定的<em>字面量</em>, 在C99之后可以是<em>变量</em></li>
</ul>
<h3 id="本质和特征">本质和特征</h3>
<p>数组的本质是一个<strong>容器</strong> <em>(放东西的东西)</em></p>
<blockquote>
<p>就现代编程语言而言, 评判其<strong>能力大小</strong>的一项标准, 就是该语言<strong>提供容器的能力</strong></p>
</blockquote>
<h3 id="数组的特点">数组的特点</h3>
<ul>
<li>所有元素都具有<strong>相同</strong>的数据类型</li>
<li>数组的<strong>大小</strong>一旦创建就<strong>不得改变</strong></li>
<li>在内存中, 数组中的元素是紧密、连续、<strong>依次排列</strong>的</li>
</ul>
<h3 id="数组的单元下标">数组的单元、下标</h3>
<p>数组的每个单元就是数组类型的一个<strong>变量</strong><br>
使用数组时放在<code>[]</code>中的数字称为 <strong>下标</strong> or <strong>索引</strong><br>
下标是从<code>0</code>开始计数的</p>
<blockquote>
<p>虽然数组并不是C语言发明的, 但下标从<code>0</code>开始计数是从C语言开始的<br>
重要的原因是, C语言的编译器可以简化很多</p>
</blockquote>
<h3 id="有效的下标范围">有效的下标范围</h3>
<p>编译器和运行环境<strong>不会检查</strong>数组的下标是否越界(无论读写)<br>
可能会造成<strong>报错/警告</strong>: <code>segmentation fault</code></p>
<p><code>int a[0]</code><br>
长度为<code>0</code>的数组可以存在, 但毫无用处, 因为不存在有效的下标范围</p>
<h2 id="数组的集成初始化">数组的集成初始化</h2>
<h3 id="定义">定义</h3>
<p><code>int a[] = {1,22,333}</code>这种写法被称为 <strong>数组的集成初始化</strong></p>
<ul>
<li>直接用大括号给出数组中所有元素的初始值</li>
<li>不需要给出数组的大小, 编译器会自动计数</li>
</ul>
<h3 id="写法注意">写法注意</h3>
<p>注意: 如果是这种写法<br>
<code>int a[5]={2,3};</code><br>
其效果<strong>等同于</strong><br>
<code>int a[]={2,3,0,0,0};</code></p>
<h3 id="集成初始化时的定位">集成初始化时的定位</h3>
<p>在<em><strong>C99</strong></em>中, 允许用<code>[n]</code>在初始化数据中给出<strong>定位</strong><br>
没有定位的数据接在前面的位置后面<br>
其他位置填补零<br>
如果不给出数组大小, 编译器会把涉及到的最大的位置定为数组的长度<br>
这种写法特变适合<em>初始数据稀疏</em>的数组</p>
<pre tabindex="0"><code>int a[8] = {
  [0]=2, [2]=3, 6,
};
</code></pre><p>上面的写法<strong>等同于</strong><br>
<code>int a[8] = {2,0,3,6,0,0,0,0};</code></p>
<p><code>int a[] = {[3] = 1, 2, 3, [5] = 6, 7, 8};</code><br>
<strong>等同于</strong> ```int a[] = {0, 0, 0, 1, 2, 6, 7, 8};</p>
<h2 id="数组操作">数组操作</h2>
<h3 id="数组长度">数组长度</h3>
<pre tabindex="0"><code>int a[]={1,2,3,};
int length_a = sizeof(a)/sizeof(a[0]); 
</code></pre><p>这个小技巧对于所有数组都成立</p>
<blockquote>
<p>有趣的是在定义数组时, 最后多出来的那个<code>,</code><br>
这是为了后来人不用再打上逗号而准备的, 对程序来说<strong>毫无影响</strong><br>
这么做可以显得自己读过70/80年代的编程书</p>
</blockquote>
<h3 id="数组赋值">数组赋值</h3>
<pre tabindex="0"><code>int a[]={1,2,3,};
int b[]=a;
</code></pre><p>这么做无法将数组<code>a</code>赋值给数组<code>b</code><br>
唯一方法是<strong>遍历数组</strong></p>
<h2 id="数组的应用">数组的应用</h2>
<h3 id="搜索">搜索</h3>
<p>在一个数组中找出要找的数字</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

int search(int key, int a[], int length);

int main()
{
    int a[] = {2, 4, 6, 82, 455, 1, 10, 54, 4, 3, 5, 17, 14, 32, 8};
    int x;
    int loc;
    printf(&#34;请输入一个数字: &#34;);
    scanf(&#34;%d&#34;, &amp;x);
    loc = search(x, a, sizeof(a) / sizeof(a[0]));
    if (loc != -1)
    {
        printf(&#34;%d在第%d个位置上\n&#34;, x, loc);
    }
    else
    {
        printf(&#34;%d不存在\n&#34;, x);
    }

    return 0;
}

int search(int key, int a[], int length)
{
    int ret = -1;
    for (int i = 0; i &lt; length; i++)
    {
        if (a[i] == key)
        {
            ret = i;
            break;
        }
    }
    return ret;
}
</code></pre><p>这里注意: 数组作为函数的参数时, 往往要求用另一个参数来传入<strong>数组的大小</strong><br>
这是因为当数组作为参数时:</p>
<ul>
<li>不能再利用<em><strong>sizeof</strong></em>来计算数组的元素个数</li>
<li>也就无法计算数组的大小</li>
</ul>
<h3 id="素数判断">素数判断</h3>
<blockquote>
<p>如果使用素数去判断数字是否是素数, 时间复杂度最低<br>
但仅仅在构造素数表的时候有用</p>
</blockquote>
<p>以下代码用于找出前100个素数</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

int isPrime(int x, int knownPrimes[], int length);

int main()
{
    const int number = 100;
    int prime[number];
    prime[0] = 2;
    int count = 1;
    int i = 3;
    while (count &lt; number)
    {
        if (isPrime(i, prime, count))
        {
            prime[count++] = i;
        }
        i++;
    }

    for (i = 0; i &lt; number; i++)
    {
        printf(&#34;%d&#34;, prime[i]);
        if ((i + 1) % 5)
            printf(&#34;\t&#34;);
        else
            printf(&#34;\n&#34;);
    }

    return 0;
}

int isPrime(int x, int knownPrimes[], int length)
{
    int ret = 1;
    for (int i = 0; i &lt; length; i++)
    {
        if (x % knownPrimes[i] == 0)
        {
            ret = 0;
            break;
        }
    }
    return ret;
}
</code></pre><p>如果说想构造<code>n</code>以内的素数表, 可以采用挖空法<br>
即, 挖掉所有倍数<br>
以下求出25以内的素数</p>
<pre tabindex="0"><code>int main()
{
    const int number = 25;
    int isPrime[number];
    for (int i = 0; i &lt; number; i++)
    {
        isPrime[i] = 1;
    }

    for (int x = 2; x &lt; number; x++)
    {
        if (isPrime[x])
        {
            for (int i = 2; i * x &lt; number; i++)
            {
                isPrime[i * x] = 0;
            }
        }
    }
    for (int i = 2; i &lt; number; i++)
    {
        if (isPrime[i])
        {
            printf(&#34;%d\t&#34;, i);
        }
    }
    printf(&#34;\n&#34;);

    return 0;
}
</code></pre><blockquote>
<p>要多多考虑时间复杂度, 有时候不能被人的思维所局限</p>
</blockquote>
<h2 id="二维数组">二维数组</h2>
<p><code>int a[3][5]</code>通常被理解为一个<em>3行5列的矩阵</em></p>
<h3 id="内存中的排布">内存中的排布</h3>
<table>
<thead>
<tr>
<th style="text-align:center"></th>
<th style="text-align:center"></th>
<th style="text-align:center"></th>
<th style="text-align:center"></th>
<th style="text-align:center"></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">a[0][0]</td>
<td style="text-align:center">a[0][1]</td>
<td style="text-align:center">a[0][2]</td>
<td style="text-align:center">a[0][3]</td>
<td style="text-align:center">a[0][4]</td>
</tr>
<tr>
<td style="text-align:center">a[1][0]</td>
<td style="text-align:center">a[1][1]</td>
<td style="text-align:center">a[1][2]</td>
<td style="text-align:center">a[1][3]</td>
<td style="text-align:center">a[1][4]</td>
</tr>
<tr>
<td style="text-align:center">a[2][0]</td>
<td style="text-align:center">a[2][1]</td>
<td style="text-align:center">a[2][2]</td>
<td style="text-align:center">a[2][3]</td>
<td style="text-align:center">a[2][4]</td>
</tr>
</tbody>
</table>
<h3 id="遍历">遍历</h3>
<pre tabindex="0"><code>for (i = 0; i &lt; 3; i++)
{
    for (j = 0; j &lt; 3; j++)
    {
        a[i][j] = i * j;
    }
}
</code></pre><blockquote>
<p>平时数学上的 $a[i,j]$ 表示坐标系中的一个点<br>
但在C语言中, 由于<code>,</code>是一个运算符<br>
<code>a[i,j]</code>和<code>a[j]</code>是等价的, 这显然不是正确的表达二维数组的方式</p>
</blockquote>
<h3 id="初始化">初始化</h3>
<pre tabindex="0"><code>int a[][5] = {
    {0, 1, 2, 3, 4},
    {2, 3, 4, 5, 6},
};
</code></pre><p><strong>列数必须给出</strong>, 行数可以省略<br>
其他一些细节和一位数组一致</p>
<blockquote>
<p>其实可以用一长串数字初始化<br>
因为这与内存中的结构实质上一致<br>
为了人类读者阅读方便, 还是用<code>{}</code>来写较好</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>L6_函数___2022-11-07</title>
			<link>https://zhydada.github.io/posts/l6_%E5%87%BD%E6%95%B0___2022-11-07/</link>
			<pubDate>Mon, 07 Nov 2022 22:08:39 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l6_%E5%87%BD%E6%95%B0___2022-11-07/</guid>
			<description>目录 引入 定义与使用 什么是函数? 函数的定义 函数的调用 函数的返回 函数的原型 函数定义与调用先后关系的讲究 函数的原型与声明 参数传递 类型不匹配 传参 本地</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%BC%95%E5%85%A5">引入</a></li>
<li><a href="#%E5%AE%9A%E4%B9%89%E4%B8%8E%E4%BD%BF%E7%94%A8">定义与使用</a>
<ul>
<li><a href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%87%BD%E6%95%B0">什么是函数?</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9A%E4%B9%89">函数的定义</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E7%9A%84%E8%B0%83%E7%94%A8">函数的调用</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E7%9A%84%E8%BF%94%E5%9B%9E">函数的返回</a></li>
</ul>
</li>
<li><a href="#%E5%87%BD%E6%95%B0%E7%9A%84%E5%8E%9F%E5%9E%8B">函数的原型</a>
<ul>
<li><a href="#%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89%E4%B8%8E%E8%B0%83%E7%94%A8%E5%85%88%E5%90%8E%E5%85%B3%E7%B3%BB%E7%9A%84%E8%AE%B2%E7%A9%B6">函数定义与调用先后关系的讲究</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E7%9A%84%E5%8E%9F%E5%9E%8B%E4%B8%8E%E5%A3%B0%E6%98%8E">函数的原型与声明</a></li>
</ul>
</li>
<li><a href="#%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92">参数传递</a>
<ul>
<li><a href="#%E7%B1%BB%E5%9E%8B%E4%B8%8D%E5%8C%B9%E9%85%8D">类型不匹配</a></li>
<li><a href="#%E4%BC%A0%E5%8F%82">传参</a></li>
</ul>
</li>
<li><a href="#%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F">本地变量</a>
<ul>
<li><a href="#%E5%8F%98%E9%87%8F%E7%9A%84%E7%94%9F%E5%AD%98%E6%9C%9F%E5%92%8C%E4%BD%9C%E7%94%A8%E5%9F%9F">变量的生存期和作用域</a></li>
<li><a href="#%E6%9C%AC%E5%9C%B0%E5%8F%98%E9%87%8F%E7%9A%84%E8%A7%84%E5%88%99">本地变量的规则</a></li>
</ul>
</li>
<li><a href="#%E8%A1%A5%E5%85%85">补充</a>
<ul>
<li><a href="#%E5%AE%9A%E4%B9%89%E6%97%A0%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0">定义无参数的函数</a></li>
<li><a href="#%E9%80%97%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6">逗号运算符</a></li>
<li><a href="#%E5%87%BD%E6%95%B0%E9%87%8C%E7%9A%84%E5%87%BD%E6%95%B0">函数里的函数</a></li>
<li><a href="#%E5%A5%87%E5%BD%A2%E6%80%AA%E7%8A%B6">奇形怪状</a></li>
<li><a href="#%E5%85%B3%E4%BA%8Emain%E5%87%BD%E6%95%B0">关于main函数</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="引入">引入</h2>
<p>求 0-10 和 20-30 和 35-45 的和</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void main()
{
    int i, sum;
    for (sum = 0, i = 1; i &lt;= 10; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, 1, 10, sum);

    for (sum = 0, i = 20; i &lt;= 30; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, 20, 30, sum);

    for (sum = 0, i = 35; i &lt;= 45; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, 35, 45, sum);
}
</code></pre><blockquote>
<p><strong>代码复制</strong>是程序<strong>质量不良</strong>的表现!</p>
<blockquote>
<p>这是因为以后做代码维护的时候要修改很多处</p>
</blockquote>
</blockquote>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void sum(int begin, int end){
    int i;
    int sum = 0;
    for (i = begin; i &lt;= end; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, begin, end, sum);
}

void main()
{
    sum(1, 10);
    sum(20, 30);
    sum(35, 45);
}
</code></pre><p>将重复部分提取出来, 方便以后的调用</p>
<h2 id="定义与使用">定义与使用</h2>
<h3 id="什么是函数">什么是函数?</h3>
<blockquote>
<p>函数是一块代码, 接收<strong>零个或多个</strong>值, <em>做一件事情</em>, 并返回<strong>零个或一个</strong>值</p>
</blockquote>
<h3 id="函数的定义">函数的定义</h3>
<pre tabindex="0"><code>void sum(int begin, int end){
    int i;
    int sum = 0;
    for (i = begin; i &lt;= end; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, begin, end, sum);
}
</code></pre><blockquote>
<p><em><strong>void</strong></em> 是返回类型<br>
<em><strong>sum</strong></em> 是函数名<br>
<em><strong>int begin, int end</strong></em> 是参数表<br>
<em><strong>花括号内的代码块</strong></em> 称为函数体</p>
</blockquote>
<h3 id="函数的调用">函数的调用</h3>
<pre tabindex="0"><code>函数名(参数值)
</code></pre><p><strong>注意</strong>: <code>()</code>起到了<strong>重要</strong>的作用</p>
<ul>
<li><code>()</code>表示前面的表达式是一个函数并且在调用ta, 而不是一个<em>函数指针</em></li>
<li>即便没有参数也要<code>()</code></li>
<li>有参数的话, 需要给出正确的 <strong>数量和顺序</strong></li>
<li>这些值会<strong>按照顺序</strong>给函数参数表中的参数(相当于变量)<strong>初始化赋值</strong></li>
</ul>
<h3 id="函数的返回">函数的返回</h3>
<p>函数<em>知道</em>每一次是哪里调用了ta, 会返回到正确的地方</p>
<h2 id="函数的原型">函数的原型</h2>
<h3 id="函数定义与调用先后关系的讲究">函数定义与调用先后关系的讲究</h3>
<p>要在调用函数<strong>的上面</strong>定义函数, 原因如下:</p>
<ul>
<li>C的编译器以<strong>自上而下</strong>的顺序分析代码</li>
<li>在遇到调用的函数的时候, ta需要知道其定义</li>
<li>即, 参数的 个数/类型/顺序</li>
<li>这样才能检查调用是否正确</li>
</ul>
<p>如果定义语句放在调用之下(且不做声明), 其结果要视<strong>编译器</strong>而定</p>
<p>比如, 如下的代码会发出<strong>警告</strong>, 在某些<em>严格</em>的编译器上甚至会出现<strong>编译失败</strong></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void main()
{
    sum(1, 10);
    sum(20, 30);
    sum(35, 45);
}

void sum(int begin, int end)
{
    int i;
    int sum = 0;
    for (i = begin; i &lt;= end; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, begin, end, sum);
}
</code></pre><blockquote>
<p>原因: 当编译器读到调用位置时, 会做出猜测, ta猜测<code>sum</code>函数的<strong>声明</strong>是如下的样子</p>
<blockquote>
<p><code>int sum (int, int)</code></p>
</blockquote>
<p>但当ta读到<code>sum</code>的<strong>定义</strong>时发现与之不符, 于是报出了<em>类型冲突</em>的警告<br>
不过有些高级编译器能自行纠正, 仍旧能正确运行代码</p>
</blockquote>
<p>联系上述分析, 如果做出如下修改就可以正确运行</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void main()
{
    sum(1, 10);
    sum(20, 30);
    sum(35, 45);
}

int sum(int begin, int end)
{
    int i;
    int sum = 0;
    for (i = begin; i &lt;= end; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, begin, end, sum);
    return sum;
}
</code></pre><blockquote>
<p>不过, 编译器仍旧会报出形如 <em>&ldquo;这个声明是我自己猜的哈&rdquo;</em> 这样的<em><strong>warning</strong></em></p>
</blockquote>
<h3 id="函数的原型与声明">函数的原型与声明</h3>
<p>函数的<strong>原型</strong>用于告诉编译器一个函数的<em>长相</em>, 包括:</p>
<ul>
<li>名称</li>
<li>参数(数量以及类型)</li>
<li>返回类型</li>
</ul>
<p>函数的<strong>声明</strong>就是展示函数原型的语句<br>
通俗来讲, <strong>声明</strong>就是告诉编译器 <em>&ldquo;你不用猜了&rdquo;</em></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void sum(int begin, int end);

void main()
{
    sum(1, 10);
    sum(20, 30);
    sum(35, 45);
}

void sum(int begin, int end)
{
    int i;
    int sum = 0;
    for (i = begin; i &lt;= end; i++)
    {
        sum += i;
    }
    printf(&#34;%d到%d的和是%d\n&#34;, begin, end, sum);
}
</code></pre><p><strong>注意</strong>:</p>
<ul>
<li>函数在<strong>声明</strong>之后, 遇到<strong>定义</strong>时, 会再次检验两者是否一致</li>
<li>现在的编程习惯是将函数的原型声明写在调用位置函数的<strong>外面</strong></li>
<li>原型中可以不用写函数的名称(即便与定义不一样也不会<em><strong>warning</strong></em>), 但一般仍旧会写上(这对于人类阅读者是有意义的)</li>
</ul>
<h2 id="参数传递">参数传递</h2>
<p>可以传递给函数的值是<strong>表达式的结果</strong>, 这就包括了:</p>
<ul>
<li>字面量</li>
<li>变量</li>
<li>函数的返回值</li>
<li>计算的结果</li>
</ul>
<h3 id="类型不匹配">类型不匹配</h3>
<p>调用函数时给的值与参数类型<strong>不匹配</strong>是C语言传统上<strong>最大的漏洞</strong><br>
编译器会<em>自作主张</em>地帮你转换类型, 但总会<strong>不尽如人意</strong></p>
<h3 id="传参">传参</h3>
<p>C语言在调用函数的时候, <strong>永远只能传值给函数</strong><br>
<strong>注意</strong>: <strong>每个函数都有自己的变量空间</strong><br>
参数也位于这个独立的空间中, 和其他函数没有关系<br>
习惯上, 参数表中的参数称作 <strong>&ldquo;形参&rdquo;</strong> , 调用函数时传入的是 <strong>&ldquo;实参&rdquo;</strong><br>
但容易产生误解, 误认为把参数传给了函数<br>
因此, 推荐称他们 <strong>&ldquo;参数&rdquo;</strong> 和 <strong>&ldquo;值&rdquo;</strong></p>
<h2 id="本地变量">本地变量</h2>
<p>函数的每次运行, 就会产生一个独立的 <strong>变量空间</strong><br>
在这个空间中的变量是只有这次运行独有的, 称作 <strong>本地变量</strong>(也可以成为<em>局部变量/自动变量</em>)</p>
<blockquote>
<p>之所以有<em>局部和本地</em>的区别是因为英文都是<em>local</em><br>
之所以叫<em>自动变量</em>, 是因为ta的<em>生存期</em>是自动的</p>
</blockquote>
<p><strong>注意</strong>:</p>
<ul>
<li>定义在<em>函数内部</em>的变量就是本地变量</li>
<li><em>参数</em>也是本地变量</li>
</ul>
<h3 id="变量的生存期和作用域">变量的生存期和作用域</h3>
<p><strong>生存期</strong> 变量开始出现到消亡<br>
<strong>作用域</strong> 在(代码的)什么范围内可以访问这个变量(即<em>可以其作用</em>)<br>
<strong>块</strong> 即一对大括号内的范围</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void swap(int x, int y)
{
    int t = x;
    x = y;
    y = t;
}
void main()
{
    int a = 5, b = 6;
    swap(a, b);
    printf(&#34;a=%d, b=%d\n&#34;, a, b);
}
</code></pre><p>上述函数的结果是: 
<code>a=5, b=6</code></p>
<blockquote>
<p>当进入swap函数的时候:</p>
<blockquote>
<p><code>a</code>和<code>b</code>仍旧存在, 即在生存期内<br>
但<code>a</code>和<code>b</code>不在作用域内, 无法在当前上下文去访问他们</p>
</blockquote>
<blockquote>
<p>作为<strong>生存</strong>来说, 他们还在<br>
作为<strong>作用</strong>来说, 他们不在当前作用域内</p>
</blockquote>
<p>当返回main函数的时候:</p>
<blockquote>
<p><code>t</code>和<code>x</code>和<code>y</code>都不存在了<br>
因为<code>swap</code>函数的运行已经结束了</p>
</blockquote>
</blockquote>
<h3 id="本地变量的规则">本地变量的规则</h3>
<ol>
<li>本地变量是定义在块内的</li>
</ol>
<ul>
<li>既可以定义在<strong>函数</strong>的块内</li>
<li>也可以定义在<strong>语句</strong>的块内</li>
</ul>
<blockquote>
<p>语句可以是<em><strong>for</strong></em>和<em><strong>if</strong></em>之类<br>
也可以随意拉一对大括号!</p>
</blockquote>
<ol start="2">
<li>程序运行进入这个块之前, 其中的变量不存在<br>
离开这个块, 其中的变量就消失了</li>
<li>块外面定义的变量在里面<strong>仍旧有效</strong></li>
<li>块里面定义了和外面<strong>同名</strong>的变量, 则以块内的为准(会掩盖外侧的)</li>
<li>不能在一个块内定义同名的变量</li>
<li>本地变量不会被默认初始化</li>
<li>参数在进入函数的时候就被初始化了(一定要给函数参数要求的值 以初始化)</li>
</ol>
<h2 id="补充">补充</h2>
<h3 id="定义无参数的函数">定义无参数的函数</h3>
<p>如果写做<code>void f(void)</code>没有任何问题<br>
在传统C中, 如果写做<code>void f()</code>, 编译器会认为传参<strong>不确定</strong>, 而非不传参</p>
<blockquote>
<p>好心的编译器又会帮你<em>猜想</em>, 然后把事情搞糟<br>
当然最糟糕的是, <strong>不报错</strong></p>
</blockquote>
<p>总之, 写<code>void f(void)</code>不会有错</p>
<blockquote>
<p>关于<code>int main()</code>的事儿, 很复杂, 在下面讨论</p>
</blockquote>
<h3 id="逗号运算符">逗号运算符</h3>
<p>之前有提到, 逗号<code>,</code>也是一种运算符, 那和调用函数时用到的<code>,</code>如何区分?</p>
<ul>
<li><em>调用函数时</em>, 圆括号中的逗号<code>,</code>是<strong>标点符号</strong></li>
<li>在<em>独立的圆括号</em>内, 表示一个运算式, 此时逗号<code>,</code>是<strong>运算符</strong></li>
</ul>
<blockquote>
<p>两个参数: f(a,b)<br>
一个参数: f((a,b))</p>
</blockquote>
<h3 id="函数里的函数">函数里的函数</h3>
<p>C语言<strong>不允许函数嵌套定义</strong><br>
可以在函数里放函数的<strong>声明</strong>, 但不能放ta的<em><strong>BODY</strong></em></p>
<h3 id="奇形怪状">奇形怪状</h3>
<p><code>int i, j, sum(int a, int b);</code><br>
这里定义的<em><strong>sum</strong></em> 函数返回为 <em><strong>int</strong></em><br>
不算错, 当然不推荐<br>
<code>return (i)</code><br>
返回 <em><strong>i</strong></em> 值而已<br>
但会误使人认为<em><strong>return</strong></em>是一个函数, 因此也不推荐</p>
<h3 id="关于main函数">关于main函数</h3>
<ul>
<li>首先, <code>int main()</code>也是一个<strong>函数</strong>, ta被称为程序的入口</li>
<li>写成<code>int main(void)</code>不会有错</li>
<li>return 的值是有意义的!!!</li>
</ul>
<blockquote>
<p>在Windows中, 用<em><strong>bat</strong></em>执行这一C语言程序, 会得到return的值<br>
如果用<code>if errorlevel 1...</code>就可以了解错误原因</p>
</blockquote>
<blockquote>
<p>一般来说, 返回0表示函数正常的运行了<br>
其他非零返回值用来表明错误原因</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>L5_数据类型___2022-10-28</title>
			<link>https://zhydada.github.io/posts/l5_%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B___2022-10-28/</link>
			<pubDate>Fri, 28 Oct 2022 22:27:47 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l5_%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B___2022-10-28/</guid>
			<description>* 对应课程: 6.1.1~ 7 目录 基础数据类型 不同之处: sizeof 整数类型 整数的内部表达 负数的表达 二进制负数 补码 数的范围 关键字 unsigned 整数越界 整数的格式化 整数的输入输出</description>
			<content type="html"><![CDATA[<p>* 对应课程:  6.1.1~ 7<br>
目录</p>
<ul>
<li><a href="#%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B">基础数据类型</a>
<ul>
<li><a href="#%E4%B8%8D%E5%90%8C%E4%B9%8B%E5%A4%84">不同之处:</a></li>
<li><a href="#sizeof">sizeof</a></li>
</ul>
</li>
<li><a href="#%E6%95%B4%E6%95%B0%E7%B1%BB%E5%9E%8B">整数类型</a>
<ul>
<li><a href="#%E6%95%B4%E6%95%B0%E7%9A%84%E5%86%85%E9%83%A8%E8%A1%A8%E8%BE%BE">整数的内部表达</a>
<ul>
<li><a href="#%E8%B4%9F%E6%95%B0%E7%9A%84%E8%A1%A8%E8%BE%BE">负数的表达</a></li>
<li><a href="#%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%B4%9F%E6%95%B0">二进制负数</a></li>
<li><a href="#%E8%A1%A5%E7%A0%81">补码</a></li>
</ul>
</li>
<li><a href="#%E6%95%B0%E7%9A%84%E8%8C%83%E5%9B%B4">数的范围</a>
<ul>
<li><a href="#%E5%85%B3%E9%94%AE%E5%AD%97-unsigned">关键字 unsigned</a></li>
<li><a href="#%E6%95%B4%E6%95%B0%E8%B6%8A%E7%95%8C">整数越界</a></li>
</ul>
</li>
<li><a href="#%E6%95%B4%E6%95%B0%E7%9A%84%E6%A0%BC%E5%BC%8F%E5%8C%96">整数的格式化</a>
<ul>
<li><a href="#%E6%95%B4%E6%95%B0%E7%9A%84%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA">整数的输入输出</a></li>
<li><a href="#8%E8%BF%9B%E5%88%B6%E5%92%8C16%E8%BF%9B%E5%88%B6">8进制和16进制</a></li>
</ul>
</li>
<li><a href="#%E9%80%89%E6%8B%A9%E6%95%B4%E6%95%B0%E7%B1%BB%E5%9E%8B">选择整数类型</a></li>
</ul>
</li>
<li><a href="#%E6%B5%AE%E7%82%B9%E7%B1%BB%E5%9E%8B">浮点类型</a>
<ul>
<li><a href="#%E6%B5%AE%E7%82%B9%E7%9A%84%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA">浮点的输入输出</a>
<ul>
<li><a href="#%E7%A7%91%E5%AD%A6%E8%AE%A1%E6%95%B0%E6%B3%95">科学计数法</a></li>
<li><a href="#%E8%BE%93%E5%87%BA%E7%B2%BE%E5%BA%A6">输出精度</a></li>
</ul>
</li>
<li><a href="#%E6%B5%AE%E7%82%B9%E7%9A%84%E8%8C%83%E5%9B%B4%E5%92%8C%E7%B2%BE%E5%BA%A6">浮点的范围和精度</a>
<ul>
<li><a href="#%E8%B6%85%E8%BF%87%E8%8C%83%E5%9B%B4%E7%9A%84%E6%B5%AE%E7%82%B9%E6%95%B0">超过范围的浮点数</a></li>
<li><a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E7%9A%84%E7%B2%BE%E5%BA%A6">浮点运算的精度</a></li>
</ul>
</li>
<li><a href="#%E6%B5%AE%E7%82%B9%E6%95%B0%E7%9A%84%E5%86%85%E9%83%A8%E8%A1%A8%E8%BE%BE">浮点数的内部表达</a></li>
<li><a href="#%E9%80%89%E6%8B%A9%E6%B5%AE%E7%82%B9%E6%95%B0%E7%B1%BB%E5%9E%8B">选择浮点数类型</a></li>
</ul>
</li>
<li><a href="#%E9%80%BB%E8%BE%91%E7%B1%BB%E5%9E%8B">逻辑类型</a>
<ul>
<li><a href="#%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97">逻辑运算</a>
<ul>
<li><a href="#%E4%BC%98%E5%85%88%E7%BA%A7">优先级</a></li>
<li><a href="#%E7%9F%AD%E8%B7%AF">短路</a></li>
<li><a href="#%E6%9D%A1%E4%BB%B6%E8%BF%90%E7%AE%97%E7%AC%A6">条件运算符</a></li>
<li><a href="#%E9%80%97%E5%8F%B7%E8%BF%90%E7%AE%97">逗号运算</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">类型转换</a>
<ul>
<li><a href="#%E8%87%AA%E5%8A%A8%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">自动类型转换</a></li>
<li><a href="#%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2">强制类型转换</a></li>
</ul>
</li>
</ul>
<hr>
<p>C是有类型的语言, 对于其变量, <strong>必须</strong>:</p>
<ul>
<li>在使用前定义</li>
<li>确定类型</li>
</ul>
<p><em>早期语言</em> 以及 <em>面向底层的语言</em> 更强调类型</p>
<ul>
<li>强类型: 有助于发现简单错误</li>
<li>弱类型: 看重事务逻辑</li>
</ul>
<blockquote>
<p><strong>C语言</strong>需要类型, 但是对类型的安全检查并不足够</p>
</blockquote>
<h1 id="基础数据类型">基础数据类型</h1>
<p>大致分为四个大类(逻辑和整数看做一类)  </p>
<table>
<thead>
<tr>
<th style="text-align:center">类别</th>
<th style="text-align:center">包括</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">整数</td>
<td style="text-align:center"><code>char</code> <code>short</code> <code>int</code> <code>long</code> <code>long long</code></td>
</tr>
<tr>
<td style="text-align:center">浮点数</td>
<td style="text-align:center"><code>float</code> <code>double</code> <code>long double</code></td>
</tr>
<tr>
<td style="text-align:center">逻辑</td>
<td style="text-align:center"><code>bool</code></td>
</tr>
<tr>
<td style="text-align:center">指针</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">自定义</td>
<td style="text-align:center"></td>
</tr>
</tbody>
</table>
<blockquote>
<p>前四种被称为 <strong>C语言的基础类型</strong> (即本身就有的)</p>
</blockquote>
<h2 id="不同之处">不同之处:</h2>
<ul>
<li>名称: <code>int</code> <code>long</code> <code>double</code></li>
<li>输入输出时的格式化: <code>%d</code> <code>%ld</code> <code>%lf</code></li>
<li>表达的范围: <code>char</code>&lt;<code>short</code>&lt;<code>int</code>&lt;<code>float</code>&lt;<code>double</code></li>
<li>内存中占据的大小: 1~16字节</li>
<li>内存中的表现形式: 整形是二进制(补码) 浮点数是编码形式(不能直接计算)</li>
</ul>
<h2 id="sizeof">sizeof</h2>
<p><code>sizeof</code>是一个运算符, 给出某个类型或者变量在内存中占据的 <strong>字节数</strong></p>
<ul>
<li><code>sizeof(int)</code></li>
<li><code>sizeof(i)</code></li>
</ul>
<p><strong>注意</strong>: <code>sizeof</code>是<em>静态的</em>, ta的括号内不会产生实际运算, 其结果<u>在编译时</u>已经<strong>确定下来</strong></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    int a = 6;
    printf(&#34;sizeof(a)=%ld\n&#34;, sizeof(a));
    printf(&#34;sizeof(a+1.0)=%ld\n&#34;, sizeof(a + 1.0));
    printf(&#34;a=%d&#34;, a);
    return 0;
}
</code></pre><p>其输出结果如下</p>
<pre tabindex="0"><code>sizeof(a)=4
sizeof(a+1.0)=8
a=6
</code></pre><h1 id="整数类型">整数类型</h1>
<p>大小比较</p>
<table>
<thead>
<tr>
<th style="text-align:center">类型</th>
<th style="text-align:center">大小</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>char</code></td>
<td style="text-align:center">1字节(8比特)</td>
</tr>
<tr>
<td style="text-align:center"><code>short</code></td>
<td style="text-align:center">2字节</td>
</tr>
<tr>
<td style="text-align:center"><code>int</code></td>
<td style="text-align:center">取决于编译器(CPU), 通常的意义是&quot;1个字&quot;</td>
</tr>
<tr>
<td style="text-align:center"><code>long</code></td>
<td style="text-align:center">取决于编译器(CPU), 通常的意义是&quot;1个字&quot;</td>
</tr>
<tr>
<td style="text-align:center"><code>long long</code></td>
<td style="text-align:center">8字节</td>
</tr>
</tbody>
</table>
<blockquote>
<p><code>1Byte = 8bit</code></p>
</blockquote>
<p><img src="http://zhyDaDa.github.io/posts/L5_%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E7%A4%BA%E6%84%8F%E5%9B%BE_1.png" alt="">
上图中 <strong>字长</strong> 是说在<em>寄存器和总线</em>中, 一份数据的大小</p>
<h2 id="整数的内部表达">整数的内部表达</h2>
<p>计算机内部一切都是二进制</p>
<ul>
<li><code>18</code> &ndash;&gt; <code>00010010</code></li>
<li><code>0</code> &ndash;&gt; <code>00000000</code></li>
<li><code>-18</code> &ndash;&gt; ?</li>
</ul>
<blockquote>
<p>一切数据类型的意义在于我们怎么看待ta</p>
</blockquote>
<h3 id="负数的表达">负数的表达</h3>
<p>计算机在处理负数时, 会把<code>-</code>视作为一种运算特殊处理, 并不看做<em>负数</em></p>
<table>
<thead>
<tr>
<th style="text-align:center">表达式</th>
<th style="text-align:center">实际运算</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">12+(-18)</td>
<td style="text-align:center">12-18</td>
</tr>
<tr>
<td style="text-align:center">12-(-18)</td>
<td style="text-align:center">12+18</td>
</tr>
<tr>
<td style="text-align:center">12*(-18)</td>
<td style="text-align:center">-(12*18)</td>
</tr>
</tbody>
</table>
<h3 id="二进制负数">二进制负数</h3>
<p>有三种方案:</p>
<ul>
<li>仿照十进制, 取一个特殊标记表示负数</li>
<li>取中间数为0, 如<code>10000000</code>为<code>0</code>, 比ta小就是负数</li>
<li><strong>补码</strong></li>
</ul>
<blockquote>
<p>第一种方案在计算时不能按照常规二进制计算, 要求特殊处理, 太复杂<br>
二方案每次在获取数据的时候总要减去<code>10000000</code>, 也很复杂</p>
</blockquote>
<h3 id="补码">补码</h3>
<p>考虑<code>-1</code>, 希望能实现<code>-1 + 1 = 0</code></p>
<ul>
<li><code>0</code> &ndash;&gt;<code>00000000</code></li>
<li><code>1</code> &ndash;&gt;<code>00000001</code></li>
<li><code>-1</code>&ndash;&gt;<code>11111111</code></li>
</ul>
<blockquote>
<p>这里<code>-1 + 1</code>的结果实际上是<code>1 00000000</code><br>
但由于表示数字的字节仅仅<em><strong>8bit</strong></em>, 所以多出来的那位被舍去, 成了<code>0</code></p>
</blockquote>
<p><code>11111111</code>被当做<strong>纯二进制</strong>看待时, 是<code>255</code><br>
但被当做<strong>补码</strong>看待时, 是<code>-1</code></p>
<p>同理, 对于<code>-a</code>, 补码就是<code>0-a</code><br>
实际上是 $2^n-a$, 其中<code>n</code>是这种类型的位数</p>
<blockquote>
<p><strong>补码的意义</strong>就是拿<em>补码和原码</em>可以加出一个溢出的<em>零</em><br>
回到之前的三种方案, 补码的优势在于<strong>不用变化符号</strong>, 直接做加法就可以得出结果</p>
</blockquote>
<h2 id="数的范围">数的范围</h2>
<p>对于一个字节(8位 即一个<em><strong>char</strong></em>), 可以表达的是:</p>
<ul>
<li><code>00000000-11111111</code></li>
</ul>
<p>其中:</p>
<table>
<thead>
<tr>
<th style="text-align:center">内存表示</th>
<th style="text-align:center">纯二进制角度</th>
<th style="text-align:center">整数角度</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>00000000</code></td>
<td style="text-align:center">0</td>
<td style="text-align:center">0</td>
</tr>
<tr>
<td style="text-align:center"><code>11111111</code> ~ <code>10000000</code></td>
<td style="text-align:center">255 ~ 128</td>
<td style="text-align:center">-1 ~ -128</td>
</tr>
<tr>
<td style="text-align:center"><code>00000001</code> ~ <code>01111111</code></td>
<td style="text-align:center">1 ~ 127</td>
<td style="text-align:center">1 ~ 127</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>注意</strong>: 这里所说的&quot;整数角度&quot;是针对<em><strong>char</strong></em>来说的<br>
不同类型有不同的角度, 下面就是个例子</p>
</blockquote>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    char c = 255;
    int i = 255;
    printf(&#34;c=%d; i=%d&#34;, c, i);
    return 0;
}
</code></pre><p>其结果为:</p>
<pre tabindex="0"><code>c=-1; i=255
</code></pre><p>分析如下:</p>
<ul>
<li>对于<em><strong>char</strong></em>来说,
<ul>
<li>大小是 <strong>8bit</strong></li>
<li>在内存中表现为 <code>11111111</code></li>
<li>解读为补码(因为首位为<code>1</code>)</li>
<li>输出为<code>-1</code></li>
</ul>
</li>
<li>对于<em><strong>int</strong></em>来说,
<ul>
<li>大小是 <strong>4Byte</strong></li>
<li>在内存中表现为 <code>00000000 00000000 00000000 11111111</code></li>
<li>解读为正整数</li>
<li>输出为<code>255</code></li>
</ul>
</li>
</ul>
<h3 id="关键字-unsigned">关键字 unsigned</h3>
<p>在定义变量的时候在类型前面添上 <strong>关键字</strong><code>unsigned</code></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    unsigned char c = 255;
    printf(&#34;c=%d&#34;, c);
    return 0;
}
</code></pre><p>运行结果:<br>
<code>c=255</code></p>
<p>如果一个字面量常数要想表达自己是<code>unsigned</code>, 在其后面加上<code>u</code>或<code>U</code></p>
<ul>
<li>例如 <code>255U</code></li>
</ul>
<blockquote>
<p><code>unsigned</code>的含义是说: 该数被视作一个正数, 不会被视作补码
其<strong>副作用</strong>就是将一个整数能表示的正数部分扩大两倍<br>
但同样地, ta就无法表示负数</p>
<blockquote>
<p>但是, <em><strong>unsigned</strong></em><strong>关键字</strong>设计的初衷并不是为了扩大正数部分<br>
而是为了做纯二进制计算, 主要是为了移位</p>
</blockquote>
</blockquote>
<h3 id="整数越界">整数越界</h3>
<p>如果不断的做<code>+1</code>运算, 到了范围的边界时<br>
考虑到之前的理论, 正整数将&quot;绕一圈&quot;变为负数<br>
用程序来说明:</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    char c = 128;
    c = c + 1;
    printf(&#34;c+1=%d\n&#34;, c);
    unsigned char u = 0;
    u = u - 1;
    printf(&#34;u-1=%d&#34;, u);
    return 0;
}
</code></pre><p>其结果是:</p>
<pre tabindex="0"><code>c+1=-127
u-1=255
</code></pre><h2 id="整数的格式化">整数的格式化</h2>
<h3 id="整数的输入输出">整数的输入输出</h3>
<p>只有两种形式: <code>int</code> 或 <code>long long</code></p>
<table>
<thead>
<tr>
<th style="text-align:center">格式</th>
<th style="text-align:center">类型</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>%d</code></td>
<td style="text-align:center"><code>int</code> <code>char</code> <code>short</code></td>
</tr>
<tr>
<td style="text-align:center"><code>%u</code></td>
<td style="text-align:center"><code>unsigned</code></td>
</tr>
<tr>
<td style="text-align:center"><code>%ld</code></td>
<td style="text-align:center"><code>long long</code></td>
</tr>
<tr>
<td style="text-align:center"><code>%lu</code></td>
<td style="text-align:center"><code>unsigned long long</code></td>
</tr>
</tbody>
</table>
<p>可以通过以下代码理解 &ldquo;数据类型重在如何看待ta&rdquo;</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    char c = -1;
    int i = -1;
    printf(&#34;c=%u, i=%u\n&#34;, c, i);
    return 0;
}
</code></pre><p>其结果为:</p>
<pre tabindex="0"><code>c=4294967295, i=4294967295
</code></pre><blockquote>
<p><code>printf</code>在接收数据时, 会把<br>
<strong>小于等于</strong><code>int</code>大小的整数类型转化为<code>int</code>传入<br>
<strong>大于</strong><code>int</code>大小的整数类型转化为<code>long</code>传入</p>
</blockquote>
<blockquote>
<p>在计算机内存的数据是<strong>同样的</strong>, 但以<strong>不同的方式</strong>看待就会有不同的结果<br>
这和计算机内部数据是什么无关, 而取决于是否以<strong>正确的方式</strong>来使用数据, 使之成为人能读懂的表示</p>
</blockquote>
<h3 id="8进制和16进制">8进制和16进制</h3>
<p><strong>字面量</strong>整数前加<code>0</code>表示 <strong>八进制</strong><br>
加<code>0x</code>表示 <strong>十六进制</strong></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    char c = 012;
    int i = 0x12;
    printf(&#34;c=%d, i=%d\n&#34;, c, i);
    return 0;
}
</code></pre><p>其结果为:</p>
<pre tabindex="0"><code>c=10, i=18
</code></pre><blockquote>
<p>同样的, 这里的进制只是我们的视角<br>
编译器仍旧会换算为二进制</p>
<blockquote>
<p><strong>进制</strong>只是表示如何把数字表达为字符串<br>
这与内部如何表达数字无关</p>
</blockquote>
</blockquote>
<p>要想输入输出:</p>
<ul>
<li><strong>八进制</strong>的格式为 <code>%o</code></li>
<li><strong>十六进制</strong>的格式为 <code>%x</code></li>
</ul>
<blockquote>
<p><strong>注意</strong>: 在十六进制中,<br>
<code>%x</code>会输出带有小写字母的十六进制数字<br>
<code>%X</code>会输出带有大写字母的十六进制数字</p>
</blockquote>
<p><strong>16进制</strong>很适合表达2进制数据<br>
因为<strong>4位二进制</strong>刚好是一个<strong>16进制位</strong><br>
而<strong>8进制</strong>的一位数字正好表达<strong>3位二进制</strong></p>
<blockquote>
<p>因此早期计算机的字长是<code>12</code>的倍数, 而非8</p>
</blockquote>
<h2 id="选择整数类型">选择整数类型</h2>
<p>为什么那么多类型?</p>
<ul>
<li>为了直接和硬件打交道(16位的类型控制芯片上的16个引脚)</li>
<li>早期语言的风格</li>
</ul>
<p><strong>建议</strong>: 没有特殊需要, 就选<em><strong>int</strong></em></p>
<ul>
<li>如今计算机CPU的字长普遍是32/64bit, 一次内存的读写正好是一个<em><strong>int</strong></em>的大小, 一次计算也是一个<em><strong>int</strong></em></li>
<li>选择更短的类型不会更快, 甚至可能更慢</li>
<li>考虑到现代编译器一般会设计 <em>内存对齐</em>, 所以更短的类型在内存中可能实际占据的也是一个<em><strong>int</strong></em>的大小<br>
(即便 <em><strong>sizeof</strong></em> 告诉你更小)</li>
</ul>
<p><em><strong>unsigned</strong></em>与否只影响输出的结果, 内部计算是<strong>一样的</strong></p>
<h1 id="浮点类型">浮点类型</h1>
<table>
<thead>
<tr>
<th style="text-align:center">类型</th>
<th style="text-align:center">字长</th>
<th style="text-align:center">范围</th>
<th style="text-align:center">有效数字</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>float</code></td>
<td style="text-align:center">32</td>
<td style="text-align:center">$\pm(1.20\times10^{-38} \sim 3.4\times10^{38})$<br>以及$0,\pm \inf,nan$</td>
<td style="text-align:center">7</td>
</tr>
<tr>
<td style="text-align:center"><code>double</code></td>
<td style="text-align:center">64</td>
<td style="text-align:center">$\pm(2.2\times10^{-308} \sim 1.79\times10^{308})$<br>以及$0,\pm \inf,nan$</td>
<td style="text-align:center">15</td>
</tr>
</tbody>
</table>
<h2 id="浮点的输入输出">浮点的输入输出</h2>
<table>
<thead>
<tr>
<th style="text-align:center">类型</th>
<th style="text-align:center"><code>scanf</code></th>
<th style="text-align:center"><code>printf</code></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>float</code></td>
<td style="text-align:center"><code>%f</code></td>
<td style="text-align:center"><code>%f, %e</code></td>
</tr>
<tr>
<td style="text-align:center"><code>double</code></td>
<td style="text-align:center"><code>%lf</code></td>
<td style="text-align:center"><code>%f, %e</code></td>
</tr>
</tbody>
</table>
<p>其中<code>%e</code>是用科学计数法输出</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    double ff = 1234.56789;
    printf(&#34;%e, %f, %E&#34;, ff, ff, ff);
    return 0;
}
</code></pre><p>其输出结果为:</p>
<pre tabindex="0"><code>1.234568e+003, 1234.567890, 1.234568E+003
</code></pre><h3 id="科学计数法">科学计数法</h3>
<p>以 <code>-5.67E+16</code> 为例子</p>
<ul>
<li>最前面可选的<code>+</code>或<code>-</code>符号</li>
<li>小数点<code>.</code>也是可选的</li>
<li>可以用<code>e</code>或<code>E</code></li>
<li>符号可以是<code>+</code>或<code>-</code>也可以省略(表示<code>+</code>)</li>
<li>整个词不能有空格</li>
</ul>
<h3 id="输出精度">输出精度</h3>
<p>在<code>%</code>和<code>f</code>之间加上<code>.n</code>可以指定输出小数点后的<code>n</code>位(做四舍五入)</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    printf(&#34;%.3f\n&#34;, -0.0049);
    printf(&#34;%.30f\n&#34;, -0.0049);
    printf(&#34;%.3f\n&#34;, -0.00049);
    return 0;
}
</code></pre><p>其结果为:</p>
<pre tabindex="0"><code>-0.005
-0.004899999999999999800000000000
-0.000
</code></pre><h2 id="浮点的范围和精度">浮点的范围和精度</h2>
<h3 id="超过范围的浮点数">超过范围的浮点数</h3>
<ul>
<li><em><strong>inf</strong></em>表示无穷大(即超出范围的浮点数)</li>
<li><em><strong>nan</strong></em>表示不存在的浮点数</li>
</ul>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
int main()
{
    printf(&#34;%f\n&#34;, 12.0 / 0.0);
    printf(&#34;%f\n&#34;, -12.0 / 0.0);
    printf(&#34;%f\n&#34;, 0.0 / 0.0);
    return 0;
}
</code></pre><p>其输出结果为:</p>
<pre tabindex="0"><code>inf
-inf
nan
</code></pre><p>也可以是:</p>
<pre tabindex="0"><code>1.#INF00
-1.#INF00
-1.#IND00
</code></pre><blockquote>
<p>考虑到现在讨论的范畴是浮点数<br>
如果用整数输出<code>12/0</code>会发生<em>编译错误</em><br>
这是因为<em><strong>nan/±inf</strong></em>为浮点数独有</p>
</blockquote>
<h3 id="浮点运算的精度">浮点运算的精度</h3>
<p><strong>注意</strong>: 浮点运算是<strong>没有精度</strong>的</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
void main()
{
    float a, b, c;
    a = 1.345f;
    b = 1.123f;
    c = a + b;
    if (c == 2.468)
        printf(&#34;相等\n&#34;);
    else
        printf(&#34;不相等! c=%.10f, 或%f\n&#34;, c, c);
}
</code></pre><p>其输出结果为:</p>
<pre tabindex="0"><code>不相等! c=2.4679999352, 或2.468000
</code></pre><blockquote>
<p>输出的结果中, 前者才是<code>c</code>真正的数值, 后者已经由于浮点数的7位有效数字做了四舍五入处理</p>
</blockquote>
<p><strong>注意</strong>:</p>
<ul>
<li>带小数点的字面量是<em><strong>double</strong></em> 而非 <em><strong>float</strong></em></li>
<li><em><strong>float</strong></em> 需要用<code>f</code>或<code>F</code>后缀来表明身份</li>
<li>在<strong>浮点计算</strong>中, <code>f1==f2</code>这类的关系判断可能失败</li>
<li>如果迫不得已, 可以通过<code>fabs(f1-f2)&lt;1e-12</code>来代替</li>
<li>其实一般<code>1e-10</code>就可以了</li>
<li>不能用浮点数来计算<strong>金额</strong>, 因为其误差会累积起来</li>
<li>只能在一定的范围内相信浮点数的计算结果, 其误差很大</li>
</ul>
<h2 id="浮点数的内部表达">浮点数的内部表达</h2>
<p>浮点数在内存中以编码形式储存</p>
<ul>
<li><strong>1bit</strong> 用与判断正负号</li>
<li><strong>11bit</strong> 用于记录指数部分</li>
<li><strong>52bit</strong> 用于记录分数部分</li>
</ul>
<blockquote>
<p>事实上实际用不了这么多位</p>
</blockquote>
<p>浮点数在计算时是由专门的硬件部件实现的<br>
计算 <em><strong>double</strong></em>和<em><strong>float</strong></em>要用的硬件部件是一样的</p>
<h2 id="选择浮点数类型">选择浮点数类型</h2>
<p>如果没有特殊需要, 只使用 <em><strong>double</strong></em></p>
<blockquote>
<p>现代CPU能够直接对<em><strong>double</strong></em>做硬件运算<br>
计算速度和存储速度都不比<em><strong>float</strong></em>慢</p>
</blockquote>
<h1 id="逻辑类型">逻辑类型</h1>
<p>C语言原先是<strong>没有</strong>布尔类型的, 用<code>0</code>和<code>非0</code>就可以判断<br>
后来引入了<em>布尔类型</em>, 由于其不是<em>原生类型</em>, 因此使用前要先加上<code>#include &lt;stdbool.h&gt;</code><br>
之后才能使用<em><strong>bool</strong></em>和<em><strong>true/false</strong></em><br>
但事实上, 在输入输出时, 布尔类型仍旧当做整数使用, 无法输出为<em><strong>true/false</strong></em></p>
<h2 id="逻辑运算">逻辑运算</h2>
<table>
<thead>
<tr>
<th style="text-align:center">运算符</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>!</code></td>
<td style="text-align:center">逻辑非</td>
</tr>
<tr>
<td style="text-align:center"><code>&amp;&amp;</code></td>
<td style="text-align:center">逻辑与</td>
</tr>
<tr>
<td style="text-align:center"><code>||</code></td>
<td style="text-align:center">逻辑或</td>
</tr>
</tbody>
</table>
<blockquote>
<p>数学中的<code>4&lt;x&lt;6</code>在程序中, 应当表示为<code>x&gt;4&amp;&amp;x&lt;6</code></p>
</blockquote>
<p>考虑这样一个例子:<br>
<code>!age &lt; 20</code></p>
<blockquote>
<p>由于逻辑非优先级最高, <code>!age</code>被结合在一起, 其结果仅可能是<code>0</code>或<code>1</code>, 那么整个表达式的结果永远为<code>1</code></p>
</blockquote>
<h3 id="优先级">优先级</h3>
<table>
<thead>
<tr>
<th style="text-align:center">优先级</th>
<th style="text-align:center">运算符</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:center"><code>()</code></td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:center"><code>! ++ --</code>和单目的<code>+ -</code></td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:center"><code>* / %</code></td>
</tr>
<tr>
<td style="text-align:center">4</td>
<td style="text-align:center"><code>+ -</code></td>
</tr>
<tr>
<td style="text-align:center">5</td>
<td style="text-align:center"><code>&lt; &lt;= &gt; &gt;=</code></td>
</tr>
<tr>
<td style="text-align:center">6</td>
<td style="text-align:center"><code>== !=</code></td>
</tr>
<tr>
<td style="text-align:center">7</td>
<td style="text-align:center"><code>&amp;&amp;</code></td>
</tr>
<tr>
<td style="text-align:center">8</td>
<td style="text-align:center"><code>||</code></td>
</tr>
<tr>
<td style="text-align:center">9</td>
<td style="text-align:center"><code>a?b:c</code></td>
</tr>
<tr>
<td style="text-align:center">10</td>
<td style="text-align:center">所有的赋值运算符</td>
</tr>
</tbody>
</table>
<h3 id="短路">短路</h3>
<p>逻辑运算是<strong>自左向右</strong>进行的, 若左侧的结果已经可以决定结果, 就<strong>不会执行</strong>右侧的计算</p>
<ul>
<li>对于<code>&amp;&amp;</code>, 左侧有<code>false</code>不做右侧</li>
<li>对于<code>||</code>, 左侧有<code>true</code>不做右侧</li>
</ul>
<h3 id="条件运算符">条件运算符</h3>
<p><code>ans = a ? b : c</code>等价于</p>
<pre tabindex="0"><code>if(a){
  ans = b;
}else{
  ans = c;
}
</code></pre><p>这种写法看似简洁, 但当嵌套起来就会出现麻烦<br>
<strong>注意</strong>: 条件运算符是自右向左结合的<br>
<code>w&lt;x ? x+w : x&lt;y ? x:y</code></p>
<blockquote>
<p>尽量不要使用嵌套的条件表达式!!!</p>
</blockquote>
<h3 id="逗号运算">逗号运算</h3>
<p>逗号是一个<strong>运算符</strong>, 用来连接两个表达式, 并以右侧表达式的值作为其结果<br>
逗号的优先级是所有运算符中最低的, 所以其两侧的表达式会先计算<br>
逗号的组合关系是自左向右, 左侧先算, 右侧后算, 取右侧的结果作为整体的结果<br>
主要用途是<em><strong>for</strong></em><br>
<code>for(i=0,j=10; i&lt;j; i++,j--)</code></p>
<h1 id="类型转换">类型转换</h1>
<p>当运算符两边出现不一致的类型时, 会自动转换成较宽/大的类型<br>
<em>宽/大</em>是指能表达的<strong>数的范围</strong>更大</p>
<h2 id="自动类型转换">自动类型转换</h2>
<p><strong>整数</strong>: char → short → int → long → long long<br>
<strong>浮点</strong>: int → float → double</p>
<p>对于<code>printf</code>, 任何小于<em><strong>int</strong></em>的类型都会被转化成<em><strong>int</strong></em><br>
<em><strong>float</strong></em>会被转化成<em><strong>double</strong></em><br>
<strong>但是</strong>, <code>scanf</code>不会</p>
<ul>
<li>要输入<code>short</code>, 需要使用<code>%hd</code></li>
<li>要输入<code>long</code>, 需要使用<code>%ld</code></li>
<li>若要以整数的形式输入<code>char</code>, 必须先得到整数再交给<code>char</code></li>
</ul>
<h2 id="强制类型转换">强制类型转换</h2>
<p>要把一个量强制转换成另一个类型(通常是较小的类型), 需要采用<code>(类型)值</code>的写法, 例如:</p>
<ul>
<li><code>(int)10.2</code></li>
<li><code>(short)32</code></li>
</ul>
<p><strong>注意</strong>:</p>
<ul>
<li>要留意<em>安全性</em>, 即大的数<strong>不一定能</strong>转换为小的数<br>
或者说, 小的变量<strong>不总能</strong>表达大的量</li>
<li>这种转换只是计算出了一个新的量, 并<strong>不会改变</strong>原来的量的值或者类型</li>
<li>强制类型转换的优先级<strong>高于</strong>四则运算</li>
</ul>
<pre tabindex="0"><code>double a = 1.0;
double b = 2.0;
int i = (int)b / a;
</code></pre><blockquote>
<p>上述的例子中, 先处理<code>(int)b</code>得到<code>2</code>, 再与浮点数<code>a</code>运算得到了浮点数的结果, 显然类型不一致, 会报错</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>背书机mobile</title>
			<link>https://zhydada.github.io/posts/%E8%83%8C%E4%B9%A6%E6%9C%BAmobile/</link>
			<pubDate>Tue, 25 Oct 2022 19:07:09 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E8%83%8C%E4%B9%A6%E6%9C%BAmobile/</guid>
			<description>自制背书机上线了! 点我跳转 mobile版 针对手机端做出大改, 所有的板块也基本改成了错题本的形式, 任意添加 终于也是完成了存档的机制, 可以不用怕</description>
			<content type="html"><![CDATA[<p><strong>自制背书机</strong>上线了!<br>
<a href="http://zhydada.github.io/EndorsementMachine/">点我跳转</a></p>
<figure class="big"><img src="http://zhydada.github.io/pics/EndorsementMachine/1.png"
         alt="image"/><figcaption>
            <p>mobile版</p>
        </figcaption>
</figure>

<p>针对手机端做出大改, 所有的板块也基本改成了错题本的形式, 任意添加<br>
终于也是完成了存档的机制, 可以不用怕错题本丢失了<br>
UI界面借鉴了<a href="http://www.nihaowua.com/home.html">心灵毒鸡汤</a>, 平时有空会来两碗, 好喝, <strong>力推</strong><br>
背景图片借用了<code>infinity-pro</code>的图库, 这是一款<em>浏览器插件</em>, 极大的美化了初始界面, <strong>力推</strong><br>
背书机是本人高三时的创意, 算是最有意义也是最大的一个项目, 下面介绍一下开发经历</p>
<hr>
<h2 id="初代">初代</h2>
<p>分别制作了三份, 分别是 古诗/三百实词/英语词组<br>
主要是考虑到老师的给出的资料很有<strong>规律性</strong><br>
灵光乍现, 利用简单的原理写成了程序</p>
<figure class="big"><img src="http://zhydada.github.io/pics/EndorsementMachine/2.png"
         alt="image"/><figcaption>
            <p>最初的单个功能</p>
        </figcaption>
</figure>

<h2 id="整合">整合</h2>
<p>功能要求上来了, 自然的组合成了一个大的<br>
既然都整合了, 顺手添点新功能呗, 于是乎制作了<strong>错题本功能</strong></p>
<figure class="big"><img src="http://zhydada.github.io/pics/EndorsementMachine/3.png"
         alt="image"/><figcaption>
            <p>整合版本</p>
        </figcaption>
</figure>

<h2 id="壁纸">壁纸</h2>
<p>考虑到每次打开电脑都能立刻将背书机映入眼帘<br>
在了解了<strong>Wallpaper Engine</strong>的制作方式后直接改装为桌面壁纸<br>
中间由于界面不适应调整了多次, 这个过程加深了我对<code>css</code>的理解<br>
最后迎战高考, 还添了一个倒计时的功能, 这个也是<em>借鉴</em>来的, 来自一个叫&quot;倒计时Countdown&quot;的大众级壁纸<br>
p.s. 倒计时的四个圆圈点上去都有不同的效果, 这是我为了使用方便定的, 未作说明<br>
p.s.p.s. 在WE还可以自定义控件样式, 就这个功能整了我一两天&hellip;</p>
<figure class="big"><img src="http://zhydada.github.io/pics/EndorsementMachine/4.png"
         alt="image"/><figcaption>
            <p>WallPaperEngine版本</p>
        </figcaption>
</figure>

<h2 id="总结">总结</h2>
<p>使用效果还是很不错的, 应该归功于资料的规律排版<br>
其实如果早一些学会<em>正则表达式</em>的话, 再乱的排版也能被快速格式化<br>
此外, 毕竟<em>借鉴</em>了不少, 背书机也只能以自用为主, 要真正做出自己的产品还有long way to go<br>
最后别忘了设计ta的初心&ndash;学习进步!</p>
<hr>
<h2 id="更新记录">更新记录</h2>
<p>2022年10月25日</p>
<ul>
<li>排版针对三种手机宽幅设计了三种UI大小, 更加适配</li>
<li>捣鼓了很久的<em><strong>flex</strong></em>排版终于像样了</li>
<li>解决了小漏洞: 输出存档功能是没问题了, 但显示在屏幕上的时候, &ldquo;<br>&ldquo;会变成换行<br>
其实修改很容易&hellip; 只要把<code>innerHTML</code>改换成<code>innerText</code>就可以了</li>
<li>关于壁纸无能为力, 试图使用 <strong>API接口</strong>, 虽然但是没玩明白, 之后改进</li>
</ul>
<p>2022年10月28日</p>
<ul>
<li>把<em>载入错题</em>换成了<em>修改错题</em>, 加了一个<strong>修改现有错题</strong>的功能, 更加方便!</li>
<li>在错题输出中加入了</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>L4_循环结构___2022-10-18</title>
			<link>https://zhydada.github.io/posts/l4_%E5%BE%AA%E7%8E%AF%E7%BB%93%E6%9E%84___2022-10-18/</link>
			<pubDate>Tue, 18 Oct 2022 21:01:27 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l4_%E5%BE%AA%E7%8E%AF%E7%BB%93%E6%9E%84___2022-10-18/</guid>
			<description>* 对应课程: 4.1.1~5.3.3 目录 while 循环 do-while 循环 例子 求对数 灵魂三问 例1 猜数游戏 例2 算平均数 例3 对多位数的逆序排列 for 循环 例子 求素数 循环嵌套 跳出嵌套 方法一 接力br</description>
			<content type="html"><![CDATA[<p>* 对应课程:  4.1.1~5.3.3<br>
目录</p>
<ul>
<li><a href="#while-%E5%BE%AA%E7%8E%AF">while 循环</a></li>
<li><a href="#do-while-%E5%BE%AA%E7%8E%AF">do-while 循环</a></li>
<li><a href="#%E4%BE%8B%E5%AD%90-%E6%B1%82%E5%AF%B9%E6%95%B0">例子 求对数</a></li>
<li><a href="#%E7%81%B5%E9%AD%82%E4%B8%89%E9%97%AE">灵魂三问</a></li>
<li><a href="#%E4%BE%8B1-%E7%8C%9C%E6%95%B0%E6%B8%B8%E6%88%8F">例1 猜数游戏</a></li>
<li><a href="#%E4%BE%8B2-%E7%AE%97%E5%B9%B3%E5%9D%87%E6%95%B0">例2 算平均数</a></li>
<li><a href="#%E4%BE%8B3-%E5%AF%B9%E5%A4%9A%E4%BD%8D%E6%95%B0%E7%9A%84%E9%80%86%E5%BA%8F%E6%8E%92%E5%88%97">例3 对多位数的逆序排列</a></li>
<li><a href="#for-%E5%BE%AA%E7%8E%AF">for 循环</a></li>
<li><a href="#%E4%BE%8B%E5%AD%90-%E6%B1%82%E7%B4%A0%E6%95%B0">例子 求素数</a></li>
<li><a href="#%E5%BE%AA%E7%8E%AF%E5%B5%8C%E5%A5%97">循环嵌套</a></li>
<li><a href="#%E8%B7%B3%E5%87%BA%E5%B5%8C%E5%A5%97">跳出嵌套</a>
<ul>
<li><a href="#%E6%96%B9%E6%B3%95%E4%B8%80-%E6%8E%A5%E5%8A%9Bbreak">方法一 接力break</a></li>
<li><a href="#%E6%96%B9%E6%B3%95%E4%BA%8C-goto">方法二 goto</a></li>
</ul>
</li>
<li><a href="#%E4%BE%8B%E9%A2%98-%E6%95%B0%E5%AD%A6%E9%A2%98">例题 数学题</a></li>
<li><a href="#%E4%BE%8B%E9%A2%98-%E6%AD%A3%E5%BA%8F%E5%88%86%E8%A7%A3%E6%AD%A3%E6%95%B4%E6%95%B0">例题 正序分解正整数</a></li>
<li><a href="#%E4%BE%8B%E9%A2%98-%E6%B1%82%E6%9C%80%E5%A4%A7%E5%85%AC%E7%BA%A6%E6%95%B0">例题 求最大公约数</a>
<ul>
<li><a href="#%E6%B3%95%E4%B8%80-%E6%9C%B4%E7%B4%A0%E8%A7%A3%E6%B3%95">法一 朴素解法</a></li>
<li><a href="#%E6%B3%95%E4%BA%8C-%E8%BE%97%E8%BD%AC%E7%9B%B8%E9%99%A4%E6%B3%95">法二 辗转相除法</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="while-循环">while 循环</h2>
<pre tabindex="0"><code>while (condition) {
    code; // 循环体
}
</code></pre><p>不多解释, 更详细的请看这篇↓<br>
<a href="https://zhydada.github.io/posts/day09_while%E5%92%8Cbreak___2022-07-24_21-10/">Day09_while和break</a></p>
<h2 id="do-while-循环">do-while 循环</h2>
<pre tabindex="0"><code>do{
    code; // 循环体
} while (condition);
</code></pre><p>该结构进入循环的时候<strong>不做检查</strong>, 即, 代码至少运行一次<br>
<strong>注意</strong>: 由于圆括号<code>()</code>表示的是语句, 因此在最后<strong>一定要记得加上分号</strong><code>;</code></p>
<h2 id="例子-求对数">例子 求对数</h2>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

int main()
{
    int x;
    int ret = 0;

    printf(&#34;The num ?\n&#34;);
    scanf(&#34;%d&#34;, &amp;x);

    int t = x;
    while (x &gt; 1)
    {
        x /= 2;
        ret++;
    }
    printf(&#34;log2 of %d is %d&#34;, t, ret);

    if (pow(2, ret) != t)
    {
        printf(&#34;(approximately)&#34;);
    }

    return 0;
}
</code></pre><p><strong>小套路</strong>: <code>x</code>在参与了运算后改变了, 先用一个<code>t</code>来备份</p>
<h2 id="灵魂三问">灵魂三问</h2>
<ol>
<li>循环要执行几次?</li>
<li>循环停止时输出了什么?</li>
<li>循环结束后, 变量的值是多少?</li>
</ol>
<h2 id="例1-猜数游戏">例1 猜数游戏</h2>
<p>计算机想一个数, 告诉玩家的猜测是大还是小, 直到猜中, 最后告诉用户猜了多少次<br>
思路:</p>
<ul>
<li>随机数, 存入<code>number</code></li>
<li>一个负责记次数的变量<code>count</code>初始化为零</li>
<li>让用户输入一个数字<code>a</code></li>
<li><code>count</code>递增</li>
<li>判断两者关系, 并输出&quot;大/小&quot;</li>
<li>如果不相等返回第三步</li>
<li>否则输出&quot;猜中&quot;次数</li>
</ul>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;

int main()
{
    srand(time(0));
    int number = rand() % 100 + 1;
    int count;
    int a = 0;

    printf(&#34;我已经想好了一个1到100以内的整数\n&#34;);
    do
    {
        printf(&#34;请猜这个1到100之间的整数: &#34;);
        scanf(&#34;%d&#34;, &amp;a);
        count++;
        if (a &gt; number)
            printf(&#34;你猜的数偏大\n&#34;);
        else if (a &lt; number)
            printf(&#34;你猜的数偏小\n&#34;);
    } while (a != number);
    printf(&#34;答案正是%d, 你一共猜了%d次\n&#34;, number, count);

    return 0;
}
</code></pre><p><strong>注释</strong>:</p>
<ul>
<li><code>srand(time(0));</code>的作用是初始化随机数, 具体原理不多解释<br>
简单来说可以理解为 <em>让随机数有随机数的样子</em></li>
<li>调用<code>rand();</code>会返回一个随机的<strong>整数</strong>, 注意区别于其他语言</li>
</ul>
<h2 id="例2-算平均数">例2 算平均数</h2>
<p>输入一系列正整数, 最后输入-1表示结束, 输出平均数</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int number;
    int sum = 0;
    int count = 0;

    printf(&#34;计算平均数\n输入一系列正整数, 最后输入-1表示结束\n&#34;);
    scanf(&#34;%d&#34;, &amp;number);
    while (number != -1)
    {
        sum += number;
        count++;
        scanf(&#34;%d&#34;, &amp;number);
    }

    printf(&#34;平均数为: %.1f\n&#34;, 1.0 * sum / count);
    return 0;
}
</code></pre><h2 id="例3-对多位数的逆序排列">例3 对多位数的逆序排列</h2>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x1 = 0, x2 = 0, digit = 0, ans = 0;
    printf(&#34;\n输入一个多位正整数: &#34;);
    scanf(&#34;%d&#34;, &amp;x1);
    x2 = x1;

    /* 方法一: 逐位输出 */
    printf(&#34;\n方法一的结果: &#34;);
    while (x1 &gt; 0)
    {
        digit = x1 % 10;
        x1 /= 10;
        printf(&#34;%d&#34;, digit);
    }

    /* 方法二: 获得转换后的数字再输出 */
    while (x2 &gt; 0)
    {
        digit = x2 % 10;
        x2 /= 10;
        ans = ans * 10 + digit;
    }
    printf(&#34;\n方法二的结果: %d&#34;, ans);

    return 0;
}
</code></pre><p>输出结果如下:</p>
<blockquote>
<p>输入一个多位正整数: 700</p>
<p>方法一的结果: 007<br>
方法二的结果: 7</p>
</blockquote>
<h2 id="for-循环">for 循环</h2>
<blockquote>
<p>引入: 要算阶乘 <code>n!</code><br>
此时要有一个计数器, 特点是:<br>
开始时要声明, 每次要判断, 最后还要做<code>++</code>运算</p>
</blockquote>
<p><code>for</code> 的语法</p>
<pre tabindex="0"><code>for(count=0; count&lt;max; count++)
</code></pre><blockquote>
<p>作为理解, 可以把 <em><strong>for</strong></em> 读作 <em><strong>对于</strong></em>, 比如:</p>
<blockquote>
<p>对于一开始的<code>count=0</code>, 当<code>count&lt;max</code>时, 循环一次, 在每轮循环完成后, 使得<code>count++</code></p>
</blockquote>
</blockquote>
<blockquote>
<p>另外, 由于 <strong>计数器</strong> 在循环外没用, 因此可以在循环中定义ta</p>
</blockquote>
<p><strong>注意</strong>: <em><strong>for</strong></em> 会在循环一开始判断循环条件<br>
这一点和 <em><strong>while</strong></em> 是类似的</p>
<p>以下是求阶乘的代码 <em>(做了优化处理)</em></p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int n;
    printf(&#34;输入要求阶乘的正整数: &#34;);
    scanf(&#34;%d&#34;, &amp;n);
    int i = n;
    int ans = 1;

    for (; n &gt; 1; n--)
    {
        ans *= n;
    }
    
    printf(&#34;%d 的阶乘为: %d\n&#34;, i, ans);
    return 0;
}
</code></pre><p>该程序以巧妙的方式, 考虑到了<code>n</code>为<code>0</code>或<code>1</code>的情况</p>
<h2 id="例子-求素数">例子 求素数</h2>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    printf(&#34;判断素数: &#34;);
    scanf(&#34;%d&#34;, &amp;x);

    int i;
    int isPrime = 1;
    for (i = 2; i &lt; x / 2; i++)
    {
        if (x % i == 0)
        {
            isPrime = 0;
            break;
        }
    }
    if (isPrime == 1)
    {
        printf(&#34;是素数\n&#34;);
    }
    else
    {
        printf(&#34;不是素数\n&#34;);
    }
    return 0;
}
</code></pre><blockquote>
<p>这里的 <code>break</code> 用于跳出循环<br>
还有一个关键字 <code>continue</code> 用于进入下一轮循环</p>
</blockquote>
<h2 id="循环嵌套">循环嵌套</h2>
<p>获取1~100内所有素数</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    for (x = 2; x &lt;= 100; x++)
    {
        int i;
        int isPrime = 1;
        for (i = 2; i &lt;= x / 2; i++)
        {
            if (x % i == 0)
            {
                isPrime = 0;
                break;
            }
        }
        if (isPrime == 1)
        {
            printf(&#34;%3d&#34;, x);
        }
    }
    return 0;
}
</code></pre><p>获取前50个素数</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    int count = 0;
    for (x = 2; count &lt; 50; x++)
    {
        int i;
        int isPrime = 1;
        for (i = 2; i &lt; x / 2 + 1; i++)
        {
            if (x % i == 0)
            {
                isPrime = 0;
                break;
            }
        }
        if (isPrime == 1)
        {
            count++;
            printf(&#34;%d\t&#34;, x);
            if (count % 5 == 0)
            {
                printf(&#34;\n&#34;);
            }
        }
    }
    return 0;
}
</code></pre><blockquote>
<p>值得注意的是, 本段程序的 <code>for</code> 并未使用计数器 <code>x</code> 作为<em>判断标志</em><br>
应当把 <em><strong>for</strong></em> 看作是 <em><strong>while</strong></em> 的<em>简写形式</em>, 不应当带有stereotype</p>
</blockquote>
<h2 id="跳出嵌套">跳出嵌套</h2>
<p>凑硬币</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    int one, two, five;

    printf(&#34;要凑几块钱? &#34;);
    scanf(&#34;%d&#34;, &amp;x);

    for (one = 0; one &lt;= x * 10; one++)
    {
        for (two = 0; two &lt;= x * 10 / 2; two++)
        {
            for (five = 0; five &lt;= x * 10 / 5; five++)
            {
                if (one + two * 2 + five * 5 == x * 10)
                {
                    printf(&#34;可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n&#34;, one, two, five, x);
                }
            }
        }
    }

    return 0;
}
</code></pre><p>如果只要求得到一种情况就直接<strong>跳出三个循环</strong>呢?</p>
<h3 id="方法一-接力break">方法一 接力break</h3>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    int one, two, five;
    int exit = 0;

    printf(&#34;要凑几块钱? &#34;);
    scanf(&#34;%d&#34;, &amp;x);

    for (one = 0; one &lt;= x * 10; one++)
    {
        for (two = 0; two &lt;= x * 10 / 2; two++)
        {
            for (five = 0; five &lt;= x * 10 / 5; five++)
            {
                if (one + two * 2 + five * 5 == x * 10)
                {
                    printf(&#34;可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n&#34;, one, two, five, x);
                    exit = 1;
                    break;
                }
            }
            if (exit == 1)
                break;
        }
        if (exit == 1)
            break;
    }

    return 0;
}
</code></pre><h3 id="方法二-goto">方法二 goto</h3>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    int one, two, five;
    int exit = 0;

    printf(&#34;要凑几块钱? &#34;);
    scanf(&#34;%d&#34;, &amp;x);

    for (one = 0; one &lt;= x * 10; one++)
    {
        for (two = 0; two &lt;= x * 10 / 2; two++)
        {
            for (five = 0; five &lt;= x * 10 / 5; five++)
            {
                if (one + two * 2 + five * 5 == x * 10)
                {
                    printf(&#34;可以用% 3d个一角 加% 3d个二角 加% 3d个五角 得到%d元\n&#34;, one, two, five, x);
                    goto out;
                }
            }
        }
    }
out:
    return 0;
}
</code></pre><blockquote>
<p><code>goto</code> 受人诟病的原因在于, ta破坏了程序的结构性<br>
但在上述的例子中, 其优点是非常显著的<br>
因此, <strong>仅仅</strong>在合适的场合使用<code>goto</code>, 其他地方<strong>尽量不使用</strong></p>
</blockquote>
<h2 id="例题-数学题">例题 数学题</h2>
<p>求$f(n)=\sum \limits _{i=1}^1 \frac{1}{n}$</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int n;
    int i;
    double sum = 0.0;
    printf(&#34;n: &#34;);
    scanf(&#34;%d&#34;, &amp;n);
    for (i = 1; i &lt;= n; i++)
    {
        sum += 1.0 / i;
    }
    printf(&#34;f(%d)=%f&#34;, n, sum);

    return 0;
}
</code></pre><p>求$f(n)=\sum \limits _{i=1}^1 \frac{1}{n}\cdot(-1)^{n+1}$</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int n;
    int i;
    double sign = 1.0;
    double sum = 0.0;
    printf(&#34;n: &#34;);
    scanf(&#34;%d&#34;, &amp;n);
    for (i = 1; i &lt;= n; i++)
    {
        sum += sign / i;
        sign *= -1;
    }
    printf(&#34;f(%d)=%f&#34;, n, sum);

    return 0;
}
</code></pre><h2 id="例题-正序分解正整数">例题 正序分解正整数</h2>
<p>输入非负整数, 正序输出每一位数字</p>
<ul>
<li>输入: <code>13425</code></li>
<li>输出: <code>1 3 4 2 5</code></li>
</ul>
<p><strong>注意</strong>: 最后的数字后面没有空格</p>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int x;
    int mask=1;
    printf(&#34;请输入非负整数: &#34;);
    scanf(&#34;%d&#34;, &amp;x);

    /* 先获得数位 */
    int t = x;
    while (t &gt; 9)
    {
        t /= 10;
        mask *= 10;
    } 

    /* 再逐个输出 */
    do{
        int d = x / mask;
        printf(&#34;%d&#34;, d);
        if(mask&gt;9)
            printf(&#34; &#34;);
        x %= mask;
        mask /= 10;
    } while (mask &gt; 0);
    printf(&#34;|&lt;-这是数字的末尾\n&#34;);
    return 0;
}
</code></pre><blockquote>
<p>本题综合了循环的多个技巧, 实属佳题<br>
尤其要琢磨循环的条件是什么</p>
</blockquote>
<h2 id="例题-求最大公约数">例题 求最大公约数</h2>
<p>输入两个数<code>a</code>&amp;<code>b</code>, 输出其最大公约数</p>
<ul>
<li>输入: <code>12</code> <code>18</code></li>
<li>输出: <code>6</code></li>
</ul>
<h3 id="法一-朴素解法">法一 朴素解法</h3>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int a, b;
    printf(&#34;输入两个整数: \n&#34;);
    scanf(&#34;%d %d&#34;, &amp;a, &amp;b);

    int ans = 0;
    int i;
    for (i = 1; i &lt;= a &amp;&amp; i &lt;= b; i++)
    {
        if (a % i == 0 &amp;&amp; b % i == 0)
        {
            ans = i;
        }
    }

    printf(&#34;最大公约数是: %d\n&#34;, ans);
    return 0;
}
</code></pre><blockquote>
<p>这里用到了逻辑运算, 在这个课程中还没教, 不过不算难<br>
可以看C#课程中相关的知识点: <a href="https://zhydada.github.io/posts/day06_convert%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2_%E5%8A%A0%E5%8A%A0%E5%87%8F%E5%87%8F_%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97%E4%B8%8E%E9%80%BB%E8%BE%91%E5%88%A4%E6%96%AD___2022-07-21_15-50/">Day06_Convert类型转换_加加减减_关系运算与逻辑判断</a></p>
</blockquote>
<h3 id="法二-辗转相除法">法二 辗转相除法</h3>
<p><strong>辗转相除法</strong>定义:</p>
<ol>
<li>如果<code>b</code>等于<code>0</code>, 计算结束, <code>a</code>就是最大公约数</li>
<li>否则, 计算<code>a</code>除以<code>b</code>的<em>余数</em>, 再让<code>a</code>和<code>b</code>互换</li>
<li>返回第一步</li>
</ol>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    int a, b;
    int t;
    printf(&#34;输入两个整数: \n&#34;);
    scanf(&#34;%d %d&#34;, &amp;a, &amp;b);

    while (b!=0)
    {
        t = a % b;
        a = b;
        b = t;
    }   

    printf(&#34;最大公约数是: %d\n&#34;, a);
    return 0;
}
</code></pre>]]></content>
		</item>
		
		<item>
			<title>L3_做判断___2022-10-11</title>
			<link>https://zhydada.github.io/posts/l3_%E5%81%9A%E5%88%A4%E6%96%AD___2022-10-11/</link>
			<pubDate>Tue, 11 Oct 2022 23:16:54 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l3_%E5%81%9A%E5%88%A4%E6%96%AD___2022-10-11/</guid>
			<description>* 对应课程: 3.1.1 ~ 3.2.4 目录 做判断 关系运算 优先级 否则的话 if再探 判断嵌套 级联的if-else if 多路分支 switch-case 做判断 条件判断用if, 语法如下 if(condition){ code; } 关系运</description>
			<content type="html"><![CDATA[<p>* 对应课程: 3.1.1 ~ 3.2.4<br>
目录</p>
<ul>
<li><a href="#%E5%81%9A%E5%88%A4%E6%96%AD">做判断</a></li>
<li><a href="#%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97">关系运算</a></li>
<li><a href="#%E4%BC%98%E5%85%88%E7%BA%A7">优先级</a></li>
<li><a href="#%E5%90%A6%E5%88%99%E7%9A%84%E8%AF%9D">否则的话</a></li>
<li><a href="#if%E5%86%8D%E6%8E%A2">if再探</a></li>
<li><a href="#%E5%88%A4%E6%96%AD%E5%B5%8C%E5%A5%97">判断嵌套</a></li>
<li><a href="#%E7%BA%A7%E8%81%94%E7%9A%84if-else-if">级联的if-else if</a></li>
<li><a href="#%E5%A4%9A%E8%B7%AF%E5%88%86%E6%94%AF-switch-case">多路分支 switch-case</a></li>
</ul>
<hr>
<h2 id="做判断">做判断</h2>
<p>条件判断用<code>if</code>, 语法如下</p>
<pre tabindex="0"><code>if(condition){
    code;
}
</code></pre><h2 id="关系运算">关系运算</h2>
<p>计算两个值的关系称为 <strong>关系运算</strong>  </p>
<table>
<thead>
<tr>
<th style="text-align:center">运算符</th>
<th style="text-align:center">意义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>==</code></td>
<td style="text-align:center">相等</td>
</tr>
<tr>
<td style="text-align:center"><code>!=</code></td>
<td style="text-align:center">不相等</td>
</tr>
<tr>
<td style="text-align:center"><code>&gt;``&gt;=</code></td>
<td style="text-align:center">大于(等于)</td>
</tr>
<tr>
<td style="text-align:center"><code>&lt;``&lt;=</code></td>
<td style="text-align:center">小于(等于)</td>
</tr>
</tbody>
</table>
<p><strong>注意</strong>: 
当两个值的关系与关系运算符的预期</p>
<ul>
<li>相符, 结果为整数<code>1</code></li>
<li>不符, 结果为整数<code>0</code></li>
</ul>
<h2 id="优先级">优先级</h2>
<p>所有 <u>关系运算符</u> 的优先级 比 <u>算术运算</u> <strong>低</strong><br>
但是, 比 <u>赋值运算符</u> <strong>高</strong></p>
<blockquote>
<p><code>7 &gt;= 3 + 4</code> 中先计算 <code>3 + 4</code><br>
<code>int r = a &gt; 0</code> 中先计算 <code>a &gt; 0</code></p>
</blockquote>
<p>判断相等与否的 <code>==</code>和<code>!=</code> 的优先级比其他关系运算符 <strong>低</strong><br>
而 <u>连续的关系运算</u> 是 <strong>从左到右进行的</strong></p>
<blockquote>
<p><code>5&gt;3 == 6&gt;4</code> 两个比较的结果都是<code>1</code>, 最后判断相等, 结果为<code>1</code><br>
<code>6&gt;5&gt;4</code> 先计算<code>6&gt;5</code>得到结果<code>1</code>, 接着运算<code>1&gt;4</code>, 因此结果为<code>0</code><br>
<code>a == b&gt;0</code> 先计算<code>b&gt;0</code>, 再判断其结果与<code>a</code>是否一致</p>
</blockquote>
<h2 id="否则的话">否则的话</h2>
<p>与其他语言一样, 加一个<code>else</code></p>
<pre tabindex="0"><code>if(condition){
    code 1;
}else{
    code 2;
}
</code></pre><h2 id="if再探">if再探</h2>
<p><code>if</code>语句后面 <em>未必</em> 要带上花括号<code>{}</code><br>
如果要执行的只有<strong>一行</strong>语句, 可以不用花括号</p>
<h2 id="判断嵌套">判断嵌套</h2>
<p>观察一下两组代码</p>
<pre tabindex="0"><code>/* find_max_1 */
int a, b, c;
scanf(&#34;%d %d %d&#34;, &amp;a, &amp;b, &amp;c);

int max = 0;

if ( a&gt;b ) {
    if( a&gt;c ) {
        max = a;
    } else {
        max = c;
    }
} else {
    if ( b&gt;c ) {
        max = b;
    } else {
        max = c;
    }
}

printf(&#34;The max is %d\n&#34;, max);
</code></pre><pre tabindex="0"><code>/* find_max_2 */
int a, b, c;
scanf(&#34;%d %d %d&#34;, &amp;a, &amp;b, &amp;c);

int max = 0;

if ( a&gt;b )
    if( a&gt;c )
        max = a;
    else
        max = c;
else
    if ( b&gt;c )
        max = b;
    else
        max = c;
    
printf(&#34;The max is %d\n&#34;, max);
</code></pre><p>两者在 <em>语法上</em> 完全相同<br>
但对于阅读代码的人来说会造成困扰<br>
这里需要注意两点:</p>
<ol>
<li>即便有<strong>缩进</strong>, 也<strong>不能</strong>暗示嵌套关系</li>
<li><code>else</code>会按<u>就近原则</u>去找最近的<code>if</code></li>
</ol>
<p>第二种写法显然存在着巨大的出错风险<br>
因此作为良好的编程习惯:</p>
<blockquote>
<p>在<code>if</code>或者<code>else</code>后面总是加上<code>{}</code><br>
即便只有一条语句</p>
</blockquote>
<h2 id="级联的if-else-if">级联的if-else if</h2>
<pre tabindex="0"><code>if (condition_1){
    code_1;
} else if (conditon) {
    code_2;
} else {
    code_3
}
</code></pre><blockquote>
<p>尽量别在级联的分支中做&quot;实际操作&quot;<br>
即, 最好是 <strong>&ldquo;单一出口&rdquo;</strong></p>
</blockquote>
<h2 id="多路分支-switch-case">多路分支 switch-case</h2>
<pre tabindex="0"><code>switch (condition) {
    case c_1:
        code_1;
        break;
    case c_2:
        code_2;
        break;
    case c_3:
        code_3;
        break;
    default: 
        code_4;
}
</code></pre><p><strong>注意</strong>:</p>
<ul>
<li><code>condition</code> 只能是整数型的结果</li>
<li>各个 <code>c_i</code> 可以是常数, 也可以是<em>由常数构成</em>的表达式, 但一定<strong>有确切结果</strong></li>
<li><code>case</code>只是一个<strong>路标</strong>, 在运行完ta对应的代码后并不会使得分支结构跳出, 只有<code>break</code>可以</li>
<li>一般来说, <code>case</code>和<code>break</code>都是配对的</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>L2_表达式_基本运算___2022-10-09</title>
			<link>https://zhydada.github.io/posts/l2_%E8%A1%A8%E8%BE%BE%E5%BC%8F_%E5%9F%BA%E6%9C%AC%E8%BF%90%E7%AE%97___2022-10-09/</link>
			<pubDate>Sun, 09 Oct 2022 22:50:17 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l2_%E8%A1%A8%E8%BE%BE%E5%BC%8F_%E5%9F%BA%E6%9C%AC%E8%BF%90%E7%AE%97___2022-10-09/</guid>
			<description>* 对应课程: 2.2.1 ~ 2.2.4 目录 表达式 运算符优先级 交换两个变量 复合赋值 表达式 表达式是一系列运算符和算子的组合, 用来计算一个值 运算符 (operator) 是指进行运算的行为</description>
			<content type="html"><![CDATA[<p>* 对应课程: 2.2.1 ~ 2.2.4<br>
目录</p>
<ul>
<li><a href="#%E8%A1%A8%E8%BE%BE%E5%BC%8F">表达式</a></li>
<li><a href="#%E8%BF%90%E7%AE%97%E7%AC%A6%E4%BC%98%E5%85%88%E7%BA%A7">运算符优先级</a></li>
<li><a href="#%E4%BA%A4%E6%8D%A2%E4%B8%A4%E4%B8%AA%E5%8F%98%E9%87%8F">交换两个变量</a></li>
<li><a href="#%E5%A4%8D%E5%90%88%E8%B5%8B%E5%80%BC">复合赋值</a></li>
</ul>
<hr>
<h2 id="表达式">表达式</h2>
<p><strong>表达式</strong>是一系列运算符和算子的组合, 用来计算一个值</p>
<ul>
<li><strong>运算符</strong> <em>(operator)</em> 是指进行运算的行为/动作</li>
<li><strong>算子</strong> <em>(operand)</em> 是指参与运算的值, 可能是常数/变量/函数的返回值</li>
</ul>
<p>举例: 计算时间差</p>
<blockquote>
<p>输入两组&quot;小时 时间&quot;, 结果也用相同格式打印出来</p>
</blockquote>
<pre tabindex="0"><code>int hour1, minute1;
int hour2, minute2;

scanf(&#34;%d %d&#34;, &amp;hour1, &amp;minute1);
scanf(&#34;%d %d&#34;, &amp;hour2, &amp;minute2);

int delta_time = (hour2 - hour1) * 60 + minute2 - minute1;
printf(&#34;时间差是%d小时%d分钟&#34;, delta_time/60, delta_time%60);
</code></pre><h2 id="运算符优先级">运算符优先级</h2>
<p>举例: 求平均值</p>
<blockquote>
<p>写一个程序, 输俩整数, 输出平均值</p>
</blockquote>
<pre tabindex="0"><code>int a,b;
printf(&#34;输入两个整数, 用空格空开\n&#34;);
scanf(&#34;%d %d&#34;, &amp;a, &amp;b);
double c = (a+b)/2.0;
printf(&#34;%d和%d的平均值=%f\n&#34;, a, b, c);
</code></pre><p><strong>注意:</strong></p>
<ul>
<li>两个算子的运算符属于 <strong>双目运算符</strong>, 比如<code>a+b</code><br>
类似的, 只有一个算子的成为的 <strong>单目运算符</strong>, 比如<code>a*-b</code><br>
这种情况下, 运算符<code>-</code>对应的运算称为 <strong>&ldquo;单目取负&rdquo;</strong>, 其<u>优先级高于乘法</u></li>
<li>在C语言中, <strong>赋值运算符</strong> <code>=</code> 被视作运算符, 而非特殊动作
<ul>
<li>即, 赋值也属于运算, 也有结果</li>
<li><code>a=6</code>的结果是<code>6</code></li>
<li><code>a=b=6;</code>
<ul>
<li>等价于<code>a=(b=6);</code></li>
<li>等价于<code>b=6; a=b;</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="交换两个变量">交换两个变量</h2>
<p>经典中的经典了</p>
<pre tabindex="0"><code>int a = 5;
int b = 6;
int t;

t=a;
a=b;
b=t;

printf(&#34;a=%d; b=%d&#34;,a,b);
</code></pre><p>经典方法二</p>
<pre tabindex="0"><code>int a = 5;
int b = 6;

a = b - a;
b = b - a;
a = a + b;

printf(&#34;a=%d; b=%d&#34;,a,b);
</code></pre><h2 id="复合赋值">复合赋值</h2>
<p>形如<code>+=</code> <code>-=</code> <code>*=</code> <code>/=</code> 和 <code>%=</code>的运算符称为 <strong>复合运算符</strong></p>
<blockquote>
<p><code>total+=12;</code><br>
等价于<br>
<code>total = total + 12;</code></p>
</blockquote>
<p><code>++</code> 和 <code>--</code> 是特殊的单目运算符, 称为 <strong>递增运算符</strong> 和 <strong>递减运算符</strong><br>
该运算符放在算子的前后分别叫做 <strong>前缀形式</strong> 和 <strong>后缀形式</strong><br>
其中:</p>
<ul>
<li>前缀得到的是运算之后的值</li>
<li>后缀可以理解为 <em>&ldquo;副作用&rdquo;</em>, 得到的是运算前的值(之后再加加减减)</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>L1_梦开始的地方_变量___2022-10-07</title>
			<link>https://zhydada.github.io/posts/l1_%E6%A2%A6%E5%BC%80%E5%A7%8B%E7%9A%84%E5%9C%B0%E6%96%B9_%E5%8F%98%E9%87%8F___2022-10-07/</link>
			<pubDate>Fri, 07 Oct 2022 21:29:50 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/l1_%E6%A2%A6%E5%BC%80%E5%A7%8B%E7%9A%84%E5%9C%B0%E6%96%B9_%E5%8F%98%E9%87%8F___2022-10-07/</guid>
			<description>* 对应课程: 1.3.1 ~ 2.1.5 目录 一刷C语言 第一个程序 变量 变量的定义 变量的名字 赋值和初始化 变量的类型 读取整数 常量 一刷C语言 学习平台显然是B站, 在比较了一</description>
			<content type="html"><![CDATA[<p>* 对应课程: 1.3.1 ~ 2.1.5</p>
<p>目录</p>
<ul>
<li><a href="#%E4%B8%80%E5%88%B7c%E8%AF%AD%E8%A8%80">一刷C语言</a></li>
<li><a href="#%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%A8%8B%E5%BA%8F">第一个程序</a></li>
<li><a href="#%E5%8F%98%E9%87%8F">变量</a>
<ul>
<li><a href="#%E5%8F%98%E9%87%8F%E7%9A%84%E5%AE%9A%E4%B9%89">变量的定义</a></li>
<li><a href="#%E5%8F%98%E9%87%8F%E7%9A%84%E5%90%8D%E5%AD%97">变量的名字</a></li>
<li><a href="#%E8%B5%8B%E5%80%BC%E5%92%8C%E5%88%9D%E5%A7%8B%E5%8C%96">赋值和初始化</a></li>
<li><a href="#%E5%8F%98%E9%87%8F%E7%9A%84%E7%B1%BB%E5%9E%8B">变量的类型</a></li>
</ul>
</li>
<li><a href="#%E8%AF%BB%E5%8F%96%E6%95%B4%E6%95%B0">读取整数</a></li>
<li><a href="#%E5%B8%B8%E9%87%8F">常量</a></li>
</ul>
<h2 id="一刷c语言">一刷C语言</h2>
<p>学习平台显然是<em>B站</em>, 在比较了一些视频后考虑采用<strong>翁恺</strong>老师的视频<br>
原因是: 声音好听/非机构/面向学生/朴实无华<br>
视频传送门: <a href="https://b23.tv/TgA42lr">翁恺C语言-哔哩哔哩</a></p>
<h2 id="第一个程序">第一个程序</h2>
<pre tabindex="0"><code>#include &lt;stdio.h&gt;

int main()
{
    printf(&#34;Hello World!\n&#34;);

    return 0;
}
</code></pre><ul>
<li>解释
<ul>
<li><code>printf</code>负责输出</li>
<li><code>\n</code>表示要换行</li>
<li><code>&quot;&quot;</code>间是字符串</li>
</ul>
</li>
</ul>
<h2 id="变量">变量</h2>
<h3 id="变量的定义">变量的定义</h3>
<p><code>int price=0;</code></p>
<ul>
<li>变量名: <code>price</code></li>
<li>类型: <code>int</code></li>
<li>初始值: <code>0</code></li>
</ul>
<blockquote>
<p>变量是一个保存数据的地方, 可以参与之后的计算</p>
</blockquote>
<p>变量定义的一般形式是:
<code>&lt;类型名称&gt; &lt;变量名称&gt;;</code></p>
<h3 id="变量的名字">变量的名字</h3>
<p>变量需要名字, 变量的名字是一种 <strong>&ldquo;标识符&rdquo;</strong> , 用以区别于其他变量<br>
标识符有<strong>构造规则</strong>, 基本的原则是:</p>
<ul>
<li>标识符只能由 字母/数字/下划线 组成</li>
<li>数字不得出现在第一个位置上</li>
<li>不可以将C语言的<strong>关键字</strong>用作标识符</li>
</ul>
<h3 id="赋值和初始化">赋值和初始化</h3>
<p><code>a=b</code>表示将<code>b</code>的值赋给<code>a</code></p>
<blockquote>
<p>在使用一个变量前应当对其赋值</p>
</blockquote>
<h3 id="变量的类型">变量的类型</h3>
<p><code>int</code>是一种变量的类型</p>
<blockquote>
<p>变量被确定类型后不可改变</p>
</blockquote>
<h2 id="读取整数">读取整数</h2>
<p><code>scanf(&quot;%d&quot;, &amp;price);</code><br>
这行表达式要求<code>scanf</code>函数读取下一个整数(<code>%d</code>的作用), 并将读取的结果赋值给变量<code>price</code></p>
<blockquote>
<p><code>f</code>字母的含义是&rsquo;formatted&rsquo;, 即读取的结果将被格式</p>
</blockquote>
<blockquote>
<p>在之后学完<strong>指针</strong>后将会讲解<code>&amp;</code>的含义</p>
</blockquote>
<h2 id="常量">常量</h2>
<p><code> int change = 100 - price;</code><br>
固定不变的数称为<strong>常量</strong>, 直接写在程序中的数字称为<strong>直接量</strong>(<em>literal</em>)</p>
<blockquote>
<p>上面的表达式更好的写法应当是:<br>
<code>const int AMOUNT = 100;</code></p>
<blockquote>
<p>好处是: <code>100</code>的含义不言而喻, 代表一种金额<br>
相比较而言, 原先的<code>100</code>被戏称为<em>magic number</em> (根本不知道什么意义)</p>
</blockquote>
</blockquote>
<p><code>const</code>是一个 <strong>修饰符</strong>, 加在<code>int</code>前面, 用来给这个变量加上一个<code>const</code>(<em>不变的</em>)的属性<br>
<code>const</code>属性表示, 该变量的值一旦被 <strong>初始化</strong> 就不能再做修改了</p>
<blockquote>
<p>如果尝试为其再次赋值, 将会导致编译器报错</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day20_飞行棋___2022-08-23_08-27</title>
			<link>https://zhydada.github.io/posts/day20_%E9%A3%9E%E8%A1%8C%E6%A3%8B___2022-08-23_08-27/</link>
			<pubDate>Tue, 23 Aug 2022 08:27:54 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day20_%E9%A3%9E%E8%A1%8C%E6%A3%8B___2022-08-23_08-27/</guid>
			<description>目录 游戏头 初始化地图 绘制地图 输入姓名 核心游戏机制 最后调整Main函数 总结 游戏头 作用: 输出游戏初始界面 Console.ForegroundColor = ConsoleColor.Cyan; Console.BackgroundColor = ConsoleColor.Black; Console.WriteLine(@&amp;#34; ******************************************** ******************************************** *******飞行棋游</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E6%B8%B8%E6%88%8F%E5%A4%B4">游戏头</a></li>
<li><a href="#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%9C%B0%E5%9B%BE">初始化地图</a></li>
<li><a href="#%E7%BB%98%E5%88%B6%E5%9C%B0%E5%9B%BE">绘制地图</a></li>
<li><a href="#%E8%BE%93%E5%85%A5%E5%A7%93%E5%90%8D">输入姓名</a></li>
<li><a href="#%E6%A0%B8%E5%BF%83%E6%B8%B8%E6%88%8F%E6%9C%BA%E5%88%B6">核心游戏机制</a></li>
<li><a href="#%E6%9C%80%E5%90%8E%E8%B0%83%E6%95%B4main%E5%87%BD%E6%95%B0">最后调整<em><strong>Main</strong></em>函数</a></li>
<li><a href="#%E6%80%BB%E7%BB%93">总结</a></li>
</ul>
<h2 id="游戏头">游戏头</h2>
<ul>
<li><strong>作用</strong>: 输出游戏初始界面</li>
</ul>
<pre tabindex="0"><code>Console.ForegroundColor = ConsoleColor.Cyan;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine(@&#34;
********************************************
********************************************
*******飞行棋游戏v1.0  By zhyDaDa***********
********************************************
********************************************
&#34;);
</code></pre><blockquote>
<p><code>Console.ForegroundColor</code>和<code>Console.BackgroundColor</code>分别用于设置控制台输出的<strong>前景色</strong>和<strong>背景色</strong><br>
<code>@</code>的使用能按照原格式输出<br>
但要实现彩虹配色, 就得每输出一行, 就设置一遍前景色</p>
</blockquote>
<h2 id="初始化地图">初始化地图</h2>
<ul>
<li><strong>作用</strong>: 加载地图所需要的资源, 为画地图做准备</li>
<li>地图的数据采用<em><strong>int</strong></em>存储(<em><strong>string</strong></em>更困难一些)</li>
<li>数字变成字符串的过程, 就是初始化地图的过程</li>
<li>由于所有方法都需要操作Maps数组, 因此建议使用<strong>静态字段</strong>模拟全局变量</li>
<li>定义地图的方法: 把存在特殊关卡的位置全部标出来</li>
</ul>
<pre tabindex="0"><code>/// &lt;summary&gt;
/// 初始化地图, 修改地图数组
/// &lt;/summary&gt;
public static void InitiateMap()
{
    int[] luckyTurn = { 6, 23, 40, 55, 69, 83 };    //幸运轮盘
    AddSpecialToMaps(luckyTurn, 1);
    int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };     //地雷
    AddSpecialToMaps(landMine, 2);
    int[] pause = { 9, 27, 60, 93 };    //暂停
    AddSpecialToMaps(pause, 3);
    int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };  //时空隧道
    AddSpecialToMaps(timeTunnel, 4);
}

/// &lt;summary&gt;
/// 输入一个数组, 把数组中的每个数字对应的地图位置
/// 修改为输入的数值
/// &lt;/summary&gt;
/// &lt;param name=&#34;array&#34;&gt;元素是若干索引&lt;/param&gt;
/// &lt;param name=&#34;sign&#34;&gt;要改为的数字&lt;/param&gt;
public static void AddSpecialToMaps(int[] array, int sign)
{
    for (int i = 0; i &lt; array.Length; i++)
    {
        Maps[array[i]] = sign;
    }
}
</code></pre><h2 id="绘制地图">绘制地图</h2>
<ul>
<li>符号最好是全角的</li>
</ul>
<pre tabindex="0"><code>/// &lt;summary&gt;
/// 画地图
/// &lt;/summary&gt;
public static void DrawMap()
{
    Console.ForegroundColor = ConsoleColor.White;
    //画第一行
    for (int i = 0; i &lt; 30; i++)
    {

        //如果两位玩家位置重合, 且都在地图上画一对尖括号
        if (PlayerPos[0] == PlayerPos[1] &amp;&amp; PlayerPos[0]==i)
        {
            Console.Write(&#34;&lt;&gt;&#34;);
        }
        else if (PlayerPos[0] == i)
        {
            Console.Write(&#34;Ａ&#34;);
        }
        else if (PlayerPos[0] == i)
        {
            Console.Write(&#34;Ｂ&#34;);
        }
        else
        {
            switch (Maps[i])
            {
                case 0:
                    Console.Write(&#34;□&#34;);
                    break;
                case 1:
                    Console.Write(&#34;⨷&#34;);
                    break;
                case 2:
                    Console.Write(&#34;☆&#34;);
                    break;
                case 3:
                    Console.Write(&#34;∆&#34;);
                    break;
                case 4:
                    Console.Write(&#34;卐&#34;);
                    break;
            }
        }
    }


}//这是方法的括号
</code></pre><ul>
<li>这里需要将方法抽离出来</li>
<li><strong>值得注意的是</strong>: 方法中最好不要打印控制台! 因此采用返回值的形式</li>
</ul>
<pre tabindex="0"><code>/// &lt;summary&gt;
/// 返回要画出的一个格子
/// &lt;/summary&gt;
/// &lt;param name=&#34;i&#34;&gt;对应的位置&lt;/param&gt;
/// &lt;returns&gt;对应的格子的string&lt;/returns&gt;
public static string TheStringOfTheMap(int i)
{
    string str = &#34;&#34;;
    //如果两位玩家位置重合, 且都在地图上画一对尖括号
    if (PlayerPos[0] == PlayerPos[1] &amp;&amp; PlayerPos[0] == i)
    {
        str = &#34;§&#34;;
    }
    else if (PlayerPos[0] == i)
    {
        str = &#34;Ａ&#34;;
    }
    else if (PlayerPos[0] == i)
    {
        str = &#34;Ｂ&#34;;
    }
    else
    {
        switch (Maps[i])
        {
            case 0:
                //Console.ForegroundColor = ConsoleColor.White;
                str = &#34;□&#34;;
                break;
            case 1:
                //Console.ForegroundColor = ConsoleColor.Green;
                str = &#34;○&#34;;
                break;
            case 2:
                //Console.ForegroundColor = ConsoleColor.Red;
                str = &#34;☆&#34;;
                break;
            case 3:
                //Console.ForegroundColor = ConsoleColor.Blue;
                str = &#34;↓&#34;;
                break;
            case 4:
                //Console.ForegroundColor = ConsoleColor.DarkMagenta;
                str = &#34;卐&#34;;
                break;
        }
    }

    return str;
}
</code></pre><blockquote>
<p>p.s. 事实上, 要想让这些奇怪的符号在控制台排列整齐, 需要调整字体为黑体(win11特有)<br>
p.s.p.s. 那些个//是原本想要变换颜色的, 不知怎么的产生了奇怪的错位, 于是乎放弃<br>
p.s.p.s.p.s. 说不定以后自己(or读者)有可能调试成功, 我记录一下我逐步调试的发现:</p>
<blockquote>
<p>就是当变色之后, 下一个要打印的字符会把之前打印的所有字符当成是半角的字符<br>
ta就会跑到前面去, 接下来的字符就会和先前打印的重合造成重影</p>
</blockquote>
</blockquote>
<ul>
<li>小竖行的处理相对简单, 只要打印空格就行</li>
<li>请注意空格数量</li>
</ul>
<pre tabindex="0"><code>//换行
Console.WriteLine();

//画第一个数列(就一个)
for (int i = 30; i &lt; 35; i++)
{
    for (int j = 0; j &lt;= 28; j++)
    {
        Console.Write(&#34;  &#34;);
    }
    Console.Write(TheStringOfTheMap(i));
    Console.WriteLine();
}
</code></pre><h2 id="输入姓名">输入姓名</h2>
<ul>
<li>经典的判断</li>
<li>小问题: 全部输入空格的话其实应该是不被允许的(虽然这样没什么不好)</li>
</ul>
<pre tabindex="0"><code>#region 输入玩家姓名
Console.WriteLine(&#34;请输入玩家A的姓名&#34;);
PlayerNames[0] = Console.ReadLine();
while (PlayerNames[0] == &#34;&#34;)
{
    Console.WriteLine(&#34;玩家姓名不得为空, 请重新输入&#34;);
    PlayerNames[0] = Console.ReadLine();
}

Console.WriteLine(&#34;请输入玩家B的姓名&#34;);
PlayerNames[1] = Console.ReadLine();
while (PlayerNames[1] == &#34;&#34;|| PlayerNames[1]== PlayerNames[0])
{
    if (PlayerNames[1] == &#34;&#34;)
    {
        Console.WriteLine(&#34;玩家姓名不得为空, 请重新输入&#34;);
    }
    else
    {
        Console.WriteLine(&#34;玩家姓名不得相同, 请重新输入&#34;);
    }
    PlayerNames[1] = Console.ReadLine();
}
#endregion
</code></pre><h2 id="核心游戏机制">核心游戏机制</h2>
<pre tabindex="0"><code>public static void PlayGame(int playerNumber)
{
    Console.WriteLine(&#34;{0}按任意键开始投掷骰子&#34;, PlayerNames[playerNumber]);
    Console.ReadKey(true);
    Random r = new Random();
    int rNumber = r.Next(1, 7);
    Console.WriteLine(&#34;{0}投出了点数{1}, 并向前移动{1}格, 按任意键行动&#34;, PlayerNames[playerNumber], rNumber);
    PlayerPos[playerNumber] += rNumber;
    ChangePos();
    Console.ReadKey(true);
    //判断踩到的格子的情况
    if (PlayerPos[0] == PlayerPos[1])
    {
        Console.WriteLine(&#34;玩家{0}踩到了玩家{1}, 玩家{2}退6格&#34;, PlayerNames[playerNumber], PlayerNames[1 - playerNumber], PlayerNames[1 - playerNumber]);
        PlayerPos[1 - playerNumber] -= 6;
        ChangePos();
        Console.ReadKey(true);
    }
    else
    {
        switch (Maps[PlayerPos[playerNumber]])
        {
            case 0:
                Console.WriteLine(&#34;玩家{0}踩到了普通方块, 安全&#34;, PlayerNames[playerNumber]);
                Console.ReadKey(true);
                break;
            case 1:
                Console.WriteLine(&#34;玩家{0}踩到了幸运轮盘, 请选择:\n1---交换位置\t2---轰炸对方&#34;, PlayerNames[playerNumber]);
                string input = Console.ReadLine();
                while (true)
                {
                    if (input == &#34;1&#34;)
                    {
                        Console.WriteLine(&#34;玩家{0}和玩家{1}互换位置&#34;, PlayerNames[playerNumber], PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        int temp = PlayerPos[0];
                        PlayerPos[0] = PlayerPos[1];
                        PlayerPos[1] = temp;
                        Console.WriteLine(&#34;交换成功! 按任意键继续&#34;);
                        Console.ReadKey(true);
                        break;
                    }
                    else if (input == &#34;2&#34;)
                    {
                        Console.WriteLine(&#34;玩家{0}轰炸了玩家{1}&#34;, PlayerNames[playerNumber], PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        PlayerPos[1-playerNumber] -= 6;
                        ChangePos();
                        Console.WriteLine(&#34;玩家{0}退了6格! 按任意键继续&#34;, PlayerNames[1 - playerNumber]);
                        Console.ReadKey(true);
                        break;
                    }
                    Console.WriteLine(&#34;只允许输入1或2, 1---交换位置\t2---轰炸对方&#34;);
                    input = Console.ReadLine();
                }
                break;
            case 2:
                Console.WriteLine(&#34;玩家{0}踩到了地雷, 退六格&#34;, PlayerNames[playerNumber]);
                PlayerPos[playerNumber] -= 6;
                ChangePos();
                Console.ReadKey(true);
                break;
            case 3:
                Console.WriteLine(&#34;玩家{0}踩到了暂停, 下一回合跳过&#34;, PlayerNames[playerNumber]);
                Flags[playerNumber] = true;
                Console.ReadKey(true);
                break;
            case 4:
                Console.WriteLine(&#34;玩家{0}踩到了时空隧道, 前进10格&#34;, PlayerNames[playerNumber]);
                PlayerPos[playerNumber] += 10;
                ChangePos();
                Console.ReadKey(true);
                break;
        }//switch的end
    }//判断的end

    ChangePos();
    Console.Clear();
    DrawMap();
}
</code></pre><blockquote>
<p>为了防止出现被干出地图的情况发生<br>
需要采用一个修正的机制</p>
</blockquote>
<pre tabindex="0"><code>public static void ChangePos()
{
    if (PlayerPos[0] &lt; 0)
    {
        PlayerPos[0] = 0;
    }
    if (PlayerPos[0] &gt;= 99)
    {
        PlayerPos[0] = 99;
    }
    if (PlayerPos[1] &lt; 0)
    {
        PlayerPos[1] = 0;
    }
    if (PlayerPos[1] &gt;= 99)
    {
        PlayerPos[1] = 99;
    }
}
</code></pre><h2 id="最后调整main函数">最后调整<em><strong>Main</strong></em>函数</h2>
<pre tabindex="0"><code>static void Main()
{
    GameShow();
    Console.WriteLine();
    #region 输入玩家姓名
    Console.WriteLine(&#34;请输入玩家A的姓名&#34;);
    PlayerNames[0] = Console.ReadLine();
    while (PlayerNames[0] == &#34;&#34;)
    {
        Console.WriteLine(&#34;玩家姓名不得为空, 请重新输入&#34;);
        PlayerNames[0] = Console.ReadLine();
    }

    Console.WriteLine(&#34;请输入玩家B的姓名&#34;);
    PlayerNames[1] = Console.ReadLine();
    while (PlayerNames[1] == &#34;&#34; || PlayerNames[1] == PlayerNames[0])
    {
        if (PlayerNames[1] == &#34;&#34;)
        {
            Console.WriteLine(&#34;玩家姓名不得为空, 请重新输入&#34;);
        }
        else
        {
            Console.WriteLine(&#34;玩家姓名不得相同, 请重新输入&#34;);
        }
        PlayerNames[1] = Console.ReadLine();
    }
    #endregion
    //输入完姓名, 清屏
    Console.Clear();


    GameShow();
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine(&#34;{0}的位置用A表示&#34;, PlayerNames[0]);
    Console.WriteLine(&#34;{0}的位置用B表示&#34;, PlayerNames[1]);
    Console.WriteLine(&#34;两人重合的位置用§表示&#34;);


    InitiateMap();
    DrawMap();

    //只要没到终点一直循环
    while (PlayerPos[0] &lt; 99 &amp;&amp; PlayerPos[1] &lt; 99)
    {
        if (!Flags[0])
        {
            PlayGame(0);
        }
        else { Flags[0] = false; }
        if (PlayerPos[0] &gt;= 99)
        {
            Console.BackgroundColor = ConsoleColor.Red;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(&#34;玩家{0}获胜!!!&#34;, PlayerNames[0]);
            break;
        }
        if (!Flags[1])
        {
            PlayGame(1);
        }
        else { Flags[1] = false; }
        if (PlayerPos[1] &gt;= 99)
        {
            Console.BackgroundColor = ConsoleColor.Red;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(&#34;玩家{0}获胜!!!&#34;, PlayerNames[1]);
            break;
        }
    }

    Console.ReadKey();


}
</code></pre><h2 id="总结">总结</h2>
<ul>
<li>除了字符无法设置前景和后景色, 其他都不错</li>
<li>优化的话可以考虑更多的选项</li>
<li>以及, *在可以通关的前提下&quot;的随机地图(防止一整排的地雷的出现)</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Fuerte Ventura by Malika Favre</title>
			<link>https://zhydada.github.io/posts/fuerteventura_by_malika_favre/</link>
			<pubDate>Mon, 22 Aug 2022 15:29:47 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/fuerteventura_by_malika_favre/</guid>
			<description>在这里展示一下自己的临摹作品 临摹对象是来自Malika_Favre的Fuerte Ventura的6幅系列插画 简介 来源: 逛花瓣网的时候, 在形如</description>
			<content type="html"><![CDATA[<p>在这里展示一下自己的临摹作品<br>
临摹对象是来自<em>Malika_Favre</em>的<em>Fuerte Ventura</em>的6幅系列插画</p>
<h2 id="简介">简介</h2>
<ul>
<li>来源: 逛花瓣网的时候, 在形如&quot;<em>极简插画</em>&ldquo;一类词条下采集到的</li>
<li>作者: 资料来自网络
<blockquote>
<p>法国女插画师Malika Favre现旅居伦敦。她的图案设计风格很独特，有着强烈的视觉审美感，风格偏几何化和简约化，擅长用较少的元素来表达丰富的内容。她创作的所有插图都弥漫着浓浓的法国味道，除了设计，她最爱五彩斑斓的鞋子和四处旅行。</p>
</blockquote>
</li>
<li>作者的作品网站 <a href="https://www.malikafavre.com/">https://www.malikafavre.com/</a></li>
<li>该系列的图集如下</li>
</ul>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/origin.jpg"
         alt="image"/><figcaption>
            <p>合集</p>
        </figcaption>
</figure>

<h2 id="临摹评价">临摹&amp;评价</h2>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/1.png"
         alt="image"/><figcaption>
            <p>SEA</p>
        </figcaption>
</figure>

<p>第一幅临摹, 左下角的配景小人完全画坏了, 最后是无奈的用色块<em>涂</em>上去<br>
另外由于原图是模糊的, 因此远景完全没动脑筋, 直接原样照搬<br>
事实上这么做只会完美实现&quot;又费时又费力并且效果弱&quot;的效果<br>
但对她作品的曲线有了认识, 钢笔工具开始熟练</p>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/2.png"
         alt="image"/><figcaption>
            <p>HARBOUR</p>
        </figcaption>
</figure>

<p>第二幅临摹, 说实话还满意<br>
鸟是放大了另外画上去的, 效果就ok<br>
但对于原图的依赖还是很大
为了达成一模一样, 因此我疯狂排直线, 希望能重合<br>
正确的做法当然还是要达成 <strong>貌似神合</strong> 的效果<br>
即, 记住大致, 然后具体线稿自己排</p>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/3.png"
         alt="image"/><figcaption>
            <p>TOWER</p>
        </figcaption>
</figure>

<p>第三幅临摹, 较前面简单不少<br>
但对于远方的小鸟还是没能领会怎么去画<br>
其实这才是全画的精髓吧<br>
原画中的鸟应当是很精细的完成后, 再缩到极小的</p>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/4.png"
         alt="image"/><figcaption>
            <p>ROAD</p>
        </figcaption>
</figure>

<p>第四幅临摹, 有失误了<br>
马路中有一个路肩画穿模了, 没剪干净<br>
房子和路牌仍旧是无可奈何, 终究还是糊弄过去了<br>
不过这次, 由于原画的动物究竟是什么没搞懂<br>
于是乎终于自己找素材贴了个熊猫上去(搭不搭啥的已经不在意了)<br>
然鹅它的影子没处理好(败笔不是一点点orz&hellip;)</p>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/5.png"
         alt="image"/><figcaption>
            <p>DUNE</p>
        </figcaption>
</figure>

<p>第五幅可能是最快的<br>
配景小人这次用心画了, 虽然但是影子很诡异就是了<br>
远方仍旧有鸟, 依旧不知道到底怎么画的<br>
干脆换做热气球(别问脑洞)<br>
btw, 重复工具算是掌握了</p>
<figure class="big"><img src="http://zhydada.github.io/pics/Fuerteventura_by_Malika_Favre/6.png"
         alt="image"/><figcaption>
            <p>HOUSE</p>
        </figcaption>
</figure>

<p>最后一幅, 也是最满意的<br>
因为所有的鸟的细节都放大之后认真重画了<br>
包括对毛巾的描绘, 应该算是钢笔工具合格了<br>
天上的鸟自己找的食物素材, 虽然不知道怎么打阴影, 但最后的效果和画风很吻合</p>
<hr>
<ul>
<li>总之, <em>Malika Favre</em>的作品都透露着迷人的浪漫</li>
<li>对这一个系列的临摹, 即便不能领会她的章法, 但绝对领教了流畅曲线(钢笔工具)和色彩(取色器)的使用</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>小工具</title>
			<link>https://zhydada.github.io/posts/%E5%B0%8F%E5%B7%A5%E5%85%B7/</link>
			<pubDate>Wed, 17 Aug 2022 15:32:08 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E5%B0%8F%E5%B7%A5%E5%85%B7/</guid>
			<description>说明 用于特定用途的实用工具, 功能较为简易 部分有抄袭/借鉴, 如站长工具, 侵删 一览表(点击名称跳转) 名称 功能 随机数 生成随机数, 也夹带了随机密码的</description>
			<content type="html"><![CDATA[<h2 id="说明">说明</h2>
<ul>
<li>用于特定用途的实用工具, 功能较为简易</li>
<li>部分有抄袭/借鉴, 如<a href="http://www.all-tool.cn/">站长工具</a>, 侵删</li>
</ul>
<h2 id="一览表点击名称跳转">一览表(点击名称跳转)</h2>
<table>
<thead>
<tr>
<th style="text-align:center">名称</th>
<th style="text-align:center">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><a href="http://zhydada.github.io/tools/RanNum">随机数</a></td>
<td style="text-align:center">生成随机数, 也夹带了随机密码的生成工具</td>
</tr>
<tr>
<td style="text-align:center"><a href="http://zhydada.github.io/tools/keyboard">键盘按键对应数字</a></td>
<td style="text-align:center">按键盘按键, 显示其对应的<em><strong>keycode</strong></em></td>
</tr>
</tbody>
</table>
]]></content>
		</item>
		
		<item>
			<title>Day19_方法的三个练习</title>
			<link>https://zhydada.github.io/posts/day19_%E6%96%B9%E6%B3%95%E7%9A%84%E4%B8%89%E4%B8%AA%E7%BB%83%E4%B9%A0___2022-08-13_22-43/</link>
			<pubDate>Sat, 13 Aug 2022 22:43:03 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day19_%E6%96%B9%E6%B3%95%E7%9A%84%E4%B8%89%E4%B8%AA%E7%BB%83%E4%B9%A0___2022-08-13_22-43/</guid>
			<description>目录 练习1 练习2 练习3 练习1 题目: 一个string类型的数组, 要输出其中最长的字符串 参考字符串: &amp;ldquo;Bernoulli&amp;rdquo;,&amp;ldquo;Fatou&amp;rdquo;,&amp;ldquo;Euler&amp;rdquo;,&amp;ldquo;Gauss&amp;rdquo;,&amp;ldquo;Riemann&amp;rdquo;,&amp;ldquo;Neumann&amp;rdquo;,&amp;ldquo;Newton&amp;rdquo;,&amp;ldquo;Maxwell&amp;rdquo;,&amp;ldquo;Kepler&amp;rdquo;,&amp;ldquo;Leibniz&amp;rdquo;,&amp;ldquo;Lagrange&amp;rdquo; static void Main(string[] args) //Main函数 { //代码从这里走</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E7%BB%83%E4%B9%A01">练习1</a></li>
<li><a href="#%E7%BB%83%E4%B9%A02">练习2</a></li>
<li><a href="#%E7%BB%83%E4%B9%A03">练习3</a></li>
</ul>
<h2 id="练习1">练习1</h2>
<ul>
<li><strong>题目</strong>: 一个<em><strong>string</strong></em>类型的数组, 要输出其中最长的字符串</li>
<li>参考字符串: &ldquo;Bernoulli&rdquo;,&ldquo;Fatou&rdquo;,&ldquo;Euler&rdquo;,&ldquo;Gauss&rdquo;,&ldquo;Riemann&rdquo;,&ldquo;Neumann&rdquo;,&ldquo;Newton&rdquo;,&ldquo;Maxwell&rdquo;,&ldquo;Kepler&rdquo;,&ldquo;Leibniz&rdquo;,&ldquo;Lagrange&rdquo;</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    string[] names = { &#34;Bernoulli&#34;, &#34;Fatou&#34;, &#34;Euler&#34;, &#34;Gauss&#34;, &#34;Riemann&#34;, &#34;Neumann&#34;, &#34;Newton&#34;, &#34;Maxwell&#34;, &#34;Kepler&#34;, &#34;Leibniz&#34;, &#34;Lagrange&#34; };
    string max = GetLongest(names);
    Console.WriteLine(max);
}
public static string GetLongest(string[] s)
{
    string max = s[0];
    for (int i = 0; i &lt; s.Length; i++)
    {
        if (s[i].Length &gt; max.Length)
        {
            max = s[i];
        }
    }
    return max;
}
</code></pre><h2 id="练习2">练习2</h2>
<ul>
<li><strong>题目:</strong> 判断等地</li>
<li>判断依据: 90~100 为优, 80~89 为良&hellip;</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    while (true)
    {

        try
        {
            Console.WriteLine(&#34;请输入考试成绩&#34;);
            int input = Convert.ToInt32(Console.ReadLine());
            string grade = DecideGrade(input);
            Console.WriteLine(&#34;考试等地为{0}&#34;, grade);
            break;
        }
        catch
        {
            Console.WriteLine(&#34;成绩输入有误, 请重新输入&#34;);
        }
    }
    Console.ReadKey();
}
public static string DecideGrade(int s)
{
    s = s / 10;
    switch (s)
    {
        case 10:
        case 9:
            return &#34;优&#34;;
        case 8:
            return &#34;良&#34;;
        case 7:
            return &#34;次&#34;;
        case 6:
            return &#34;合格&#34;;
        default:
            return &#34;不及格&#34;;
    }
}
</code></pre><h2 id="练习3">练习3</h2>
<ul>
<li>计算任意个值的总和</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int sum = GetSum2(1, 2, 3, 4, 5, 6, 7, 8);
    Console.WriteLine(sum);
}
public static int GetSum2(params int[] nums)
{
    int sum = 0;
    for (int i = 0; i &lt; nums.Length; i++)
    {
        sum += nums[i];
    }
    return sum;
}
</code></pre><blockquote>
<p><strong>注意:</strong> 要想用方法来改变一个数值, 必须要通过返回值来实现<br>
<strong>但是,</strong> 如果是改变数组, 不需要返回值</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day18_方法的重载和递归</title>
			<link>https://zhydada.github.io/posts/day18_%E6%96%B9%E6%B3%95%E7%9A%84%E9%87%8D%E8%BD%BD%E5%92%8C%E9%80%92%E5%BD%92___2022-08-11_21-31/</link>
			<pubDate>Thu, 11 Aug 2022 21:31:08 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day18_%E6%96%B9%E6%B3%95%E7%9A%84%E9%87%8D%E8%BD%BD%E5%92%8C%E9%80%92%E5%BD%92___2022-08-11_21-31/</guid>
			<description>目录 方法的重载 方法的递归 方法的重载 概念: 方法的重载是指, 方法名称相同, 但参数不同(应对不同参数采用不同方法) 举例: WriteLine这个方法</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E6%96%B9%E6%B3%95%E7%9A%84%E9%87%8D%E8%BD%BD">方法的重载</a></li>
<li><a href="#%E6%96%B9%E6%B3%95%E7%9A%84%E9%80%92%E5%BD%92">方法的递归</a></li>
</ul>
<h2 id="方法的重载">方法的重载</h2>
<ul>
<li>概念: <strong>方法的重载</strong>是指, 方法<strong>名称相同</strong>, 但<strong>参数不同</strong>(应对不同参数采用不同方法)</li>
<li>举例: <em><strong>WriteLine</strong></em>这个方法对于各种类型的传参都生效, 因此&quot;构成重载&quot;</li>
<li>引入: 对于不同类型的两个相同类型的参数, 实现求和</li>
</ul>
<pre tabindex="0"><code>public static void M(int a, int b, out int c)
{
    c = a + b;
}
public static void M(double a, double b, out double c)
{
    c = a + b;
}
public static void M(decimal a, decimal b, out decimal c)
{
    c = a + b;
}
public static void M(string a, string b, out string c)
{
    c = a + b;
}
</code></pre><ul>
<li><strong>注意:</strong> 如果两个方法返回值不同, 但形参一致, 不能构成重载<br>
即, <strong>方法的重载和返回值没有关系</strong></li>
</ul>
<h2 id="方法的递归">方法的递归</h2>
<ul>
<li><strong>注意:</strong> 记得用<em><strong>return</strong></em>退出</li>
<li><strong>备注:</strong> <em><strong>return</strong></em>退出递归程序会逐个退出</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>DayDay17_out参数_ref参数_params可变参数___2022-08-09_20-27</title>
			<link>https://zhydada.github.io/posts/day17_out%E5%8F%82%E6%95%B0_ref%E5%8F%82%E6%95%B0_params%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0___2022-08-09_20-27/</link>
			<pubDate>Tue, 09 Aug 2022 20:27:04 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day17_out%E5%8F%82%E6%95%B0_ref%E5%8F%82%E6%95%B0_params%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0___2022-08-09_20-27/</guid>
			<description>目录 引入练习 out参数 out练习 ref参数 params可变参数 引入练习 求数组的最大值, 最小值, 总和, 平均值 由于返回多个同类型的值, 所以返回数</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%BC%95%E5%85%A5%E7%BB%83%E4%B9%A0">引入练习</a></li>
<li><a href="#out%E5%8F%82%E6%95%B0"><em><strong>out</strong></em>参数</a></li>
<li><a href="#out%E7%BB%83%E4%B9%A0"><em><strong>out</strong></em>练习</a></li>
<li><a href="#ref%E5%8F%82%E6%95%B0"><em><strong>ref</strong></em>参数</a></li>
<li><a href="#params%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0"><em><strong>params</strong></em>可变参数</a></li>
</ul>
<h2 id="引入练习">引入练习</h2>
<ul>
<li>求数组的最大值, 最小值, 总和, 平均值</li>
<li>由于返回<em>多个同类型</em>的值, 所以返回数组</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int[] numbers = { 1, 2, 3, 4, 5, 6 };
    int[] res = GetMaxMinSumAvg(numbers);
    Console.WriteLine(&#34;最大值: {0}\n最小值: {1}\n总和: {2}\n平均值: {3}&#34;, res[0], res[1], res[2], res[3]);
}
/// &lt;summary&gt;
/// 输入整数数组, 返回一个数组
/// 元素依次是: 最大值, 最小值, 总和, 平均数
/// &lt;/summary&gt;
/// &lt;param name=&#34;numbers&#34;&gt;数组&lt;/param&gt;
/// &lt;returns&gt;数组&lt;/returns&gt;
public static int[] GetMaxMinSumAvg(int[] numbers)
{
    int[] res = new int[4];
    res[0] = numbers[0];
    res[1] = numbers[0];
    res[2] = 0;
    for (int i = 0; i &lt; numbers.Length; i++)
    {
        if (numbers[i] &gt; res[0])    //修改最大值
        {
            res[0] = numbers[i];
        }
        if (numbers[i] &lt; res[1])    //修改最小值
        {
            res[1] = numbers[i];
        }
        res[2] += numbers[i];
    }
    res[3] = res[2] / numbers.Length;
    return res;
}
</code></pre><blockquote>
<p>但是, 如果要返回多个不同类型的值的时候, 返回数组就不行<br>
此时, 考虑使用<em><strong>out</strong></em>参数</p>
</blockquote>
<h2 id="out参数"><em><strong>out</strong></em>参数</h2>
<ul>
<li>
<p><em><strong>out</strong></em>参数侧重于在一个方法中返回多个不同类型的值</p>
</li>
<li>
<p><strong>注意</strong>:</p>
<ul>
<li>在<code>main函数</code>中可以不给那四个值赋值, 因为函数为其赋值</li>
<li>实参形参前面都要记得带上<em><strong>out</strong></em>关键字</li>
</ul>
</li>
<li>
<p>引入练习中使用<em><strong>out</strong></em></p>
</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int[] numbers = { 1, 2, 3, 9, 5, -6 };
    int max = 0;
    int min = 0;
    int sum = 0;
    int avg = 0;
    GetMaxMinSumAvg(numbers, out max, out min, out sum, out avg);
    Console.WriteLine(&#34;最大值: {0}\n最小值: {1}\n总和: {2}\n平均值: {3}&#34;, max, min, sum, avg);
}
/// &lt;summary&gt;
/// 计算一个整数数组的 最大值, 最小值, 总和, 平均数
/// &lt;/summary&gt;
/// &lt;param name=&#34;numbers&#34;&gt;要求的数组&lt;/param&gt;
/// &lt;param name=&#34;max&#34;&gt;多余返回的最大值&lt;/param&gt;
/// &lt;param name=&#34;min&#34;&gt;多余返回的最小值&lt;/param&gt;
/// &lt;param name=&#34;sum&#34;&gt;多余返回的总和&lt;/param&gt;
/// &lt;param name=&#34;avg&#34;&gt;多余返回的平均值&lt;/param&gt;
public static void GetMaxMinSumAvg(int[] numbers, out int max, out int min, out int sum, out int avg)
{
    max = numbers[0];
    min = numbers[0];
    sum = 0;
    for (int i = 0; i &lt; numbers.Length; i++)
    {
        if (numbers[i] &gt; max)    //修改最大值
        {
            max = numbers[i];
        }
        if (numbers[i] &lt; min)    //修改最小值
        {
            min = numbers[i];
        }
        sum += numbers[i];
    }
    avg = sum / numbers.Length;
}
</code></pre><h2 id="out练习"><em><strong>out</strong></em>练习</h2>
<ul>
<li>会提示错误原因的登录系统, 当然是要用方法的那种</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    Console.WriteLine(&#34;输入用户名&#34;);
    string name = Console.ReadLine();
    Console.WriteLine(&#34;请输入密码&#34;);
    string pwd = Console.ReadLine();
    string msg;
    bool b = IsLogin(name, pwd, out msg);
    Console.WriteLine(&#34;登录结果为: {0}\n登录信息: {1}&#34;, b, msg);

}
/// &lt;summary&gt;
/// 判断用户名和密码是否正确
/// &lt;/summary&gt;
/// &lt;param name=&#34;name&#34;&gt;用户名&lt;/param&gt;
/// &lt;param name=&#34;pwd&#34;&gt;密码&lt;/param&gt;
/// &lt;param name=&#34;msg&#34;&gt;提示信息&lt;/param&gt;
/// &lt;returns&gt;登陆成功返回true&lt;/returns&gt;
public static bool IsLogin(string name, string pwd, out string msg)
{
    if (name ==&#34;admin&#34; &amp;&amp; pwd == &#34;666666&#34;)
    {
        msg = &#34;登陆成功&#34;;
        return true;
    }
    else if (name == &#34;admin&#34;)
    {
        msg = &#34;密码错误&#34;;
        return false;
    }
    else if (pwd == &#34;666666&#34;)
    {
        msg = &#34;用户名错误&#34;;
        return false;
    }
    else
    {
        msg = &#34;未知错误&#34;;
        return false;
    }
}
</code></pre><ul>
<li>模仿<em><strong>TryParse</strong></em></li>
</ul>
<pre tabindex="0"><code>public static bool MyTryParse(string s, out int result)
{
    result = 0;
    try
    {
        result = Convert.ToInt32(s);
        return true;
    }
    catch
    {
        return false;
    }
}
</code></pre><h2 id="ref参数"><em><strong>ref</strong></em>参数</h2>
<ul>
<li><em><strong>ref</strong></em>参数能够将一个变量带入方法中进行改变, 改变完成后, 再将改变后的参数导出方法</li>
<li><strong>注意</strong>: <em><strong>ref</strong></em>参数要求在方法外必须为其赋值, 而方法内可以不赋值</li>
</ul>
<blockquote>
<p>弹幕里多次提到&quot;指针&quot;, 我理解为<em>内存地址</em></p>
</blockquote>
<ul>
<li>使用方法来交换两个int类型的变量</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int n1 = 20;
    int n2 = 99;
    SwitchTwoInt(ref n1, ref n2);
    Console.WriteLine(n1 + &#34;\n&#34; + n2);
}

public static void SwitchTwoInt(ref int n1, ref int n2)
{
    n1 = n1 - n2;
    n2 = n1 + n2;
    n1 = n2 - n1;
}
</code></pre><h2 id="params可变参数"><em><strong>params</strong></em>可变参数</h2>
<ul>
<li><em><strong>params</strong></em>可变参数能将实参列表中跟<strong>可变参数数组类型</strong>一致的元素都当做数组的元素去处理</li>
<li><strong>注意</strong>: <em><strong>params</strong></em>可变参数<strong>必须</strong>是形参列表中最后一个参数</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int sum1 = GetSum(21, 323, 3, 13, 2123, 21, 4);
    int[] nums = { 21, 323, 3, 13, 2123, 21, 4 };
    int sum2 = GetSum(nums);
    Console.WriteLine(sum1);
    Console.WriteLine(sum2);
}
public static int GetSum(params int[] nums)
{
    int sum = 0;
    for (int i = 0; i &lt; nums.Length; i++)
    {
        sum += nums[i];
    }
    return sum;
}
</code></pre>]]></content>
		</item>
		
		<item>
			<title>DayDay16_掌握方法的使用</title>
			<link>https://zhydada.github.io/posts/day16_%E6%8E%8C%E6%8F%A1%E6%96%B9%E6%B3%95%E7%9A%84%E4%BD%BF%E7%94%A8___2022-08-07_20-30/</link>
			<pubDate>Sun, 07 Aug 2022 20:30:41 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day16_%E6%8E%8C%E6%8F%A1%E6%96%B9%E6%B3%95%E7%9A%84%E4%BD%BF%E7%94%A8___2022-08-07_20-30/</guid>
			<description>目录 复习 方法的调用问题 练习1 方法的概念 练习2 两个练习 复习 常量: 赋予初始值后, 不可以重新赋值 const int number = 10; 枚举: 可以和int兼容, 和string转</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E5%A4%8D%E4%B9%A0">复习</a></li>
<li><a href="#%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%E9%97%AE%E9%A2%98">方法的调用问题</a></li>
<li><a href="#%E7%BB%83%E4%B9%A01">练习1</a></li>
<li><a href="#%E6%96%B9%E6%B3%95%E7%9A%84%E6%A6%82%E5%BF%B5">方法的概念</a></li>
<li><a href="#%E7%BB%83%E4%B9%A02">练习2</a></li>
<li><a href="#%E4%B8%A4%E4%B8%AA%E7%BB%83%E4%B9%A0">两个练习</a></li>
</ul>
<h2 id="复习">复习</h2>
<ul>
<li>常量: 赋予初始值后, <strong>不可以重新赋值</strong>
<code>const int number = 10;</code></li>
<li>枚举: 可以和<code>int</code>兼容, 和<code>string</code>转换很复杂</li>
</ul>
<pre tabindex="0"><code>public enum Gender
{
    男,
    女
}
</code></pre><pre tabindex="0"><code>string s = &#34;男&#34;;
Gender g = (Gender)Enum.Parase(typeof(Gender), s);
</code></pre><ul>
<li>结构: <strong>字段</strong>可以存储多个值, 命名的时候记得带上下划线&quot;_&quot;</li>
</ul>
<pre tabindex="0"><code>public struct Person
{
    public string _name;
    public age _age;
    public Gender _gender;
}
</code></pre><pre tabindex="0"><code>Person zsPerson;
zsPerson._name = &#34;张三&#34;;
zsPerson._age = 20;
zsPerson._gender = Gender.男
</code></pre><ul>
<li>数组: 一次性存储多个相同类型的变量<br>
数组的长度一旦声明不可改变</li>
</ul>
<pre tabindex="0"><code>int[] numbers = new int[10];
</code></pre><ul>
<li>数组操作: <strong>冒泡排序</strong></li>
</ul>
<blockquote>
<p>面试时体现领悟力使用</p>
</blockquote>
<pre tabindex="0"><code>int[] numbers = { 123, 8, 445, 26, 45, 65, 46 };
for (int i = 0; i &lt; numbers.Length - 1; i++)
{
    for (int j = 0; j &lt; numbers.Length - i - 1; j++)
    {
        if (numbers[j] &gt; numbers[j + 1])
        {
            int temp = numbers[j + 1];
            numbers[j + 1] = numbers[j];
            numbers[j] = temp;
        }
    }
}
for (int i = 0; i &lt; numbers.Length - 1; i++)
{
    Console.Write(numbers[i] + &#34;&lt;&#34;);
}
Console.Write(numbers[numbers.Length - 1]);
Console.ReadKey();
</code></pre><blockquote>
<p>平日里为了效率使用</p>
</blockquote>
<pre tabindex="0"><code>int[] numbers = { 123, 8, 445, 26, 45, 65, 46 };
Array.Sort(numbers);
for (int i = 0; i &lt; numbers.Length - 1; i++)
{
    Console.Write(numbers[i] + &#34;&lt;&#34;);
}
Console.Write(numbers[numbers.Length - 1]);
Array.Reverse(numbers);
for (int i = 0; i &lt; numbers.Length; i++)
{
    Console.WriteLine(numbers[i]);
}
Console.ReadKey();
</code></pre><h2 id="方法的调用问题">方法的调用问题</h2>
<ul>
<li>例子</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int a = 3;
    Test();
    Console.WriteLine(a);
}
public static void Test()
{
    a += 5;
}
</code></pre><blockquote>
<p>这个例子的运行结果是报错, 因为参数a在test中未命名</p>
</blockquote>
<ul>
<li>如果<strong>被调用者</strong>要获得<strong>调用者</strong>的值, 方法有二
<ul>
<li>传参</li>
<li>使用静态字段来模拟全局变量</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>public static void int _number = 10;
</code></pre><ul>
<li><strong>注意</strong>: C#中没有<strong>全局变量</strong>这一说</li>
<li>如果<strong>调用者</strong>要获得<strong>被调用者</strong>的值
<ul>
<li>用<em><strong>return</strong></em></li>
</ul>
</li>
</ul>
<h2 id="练习1">练习1</h2>
<ul>
<li>写一个方法, 判断是否是闰年</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    bool b = IsRun(2022);
    Console.WriteLine(b);
}
/// &lt;summary&gt;
/// 判断给定的年份是否是闰年
/// &lt;/summary&gt;
/// &lt;param name=&#34;year&#34;&gt;给定的年份&lt;/param&gt;
/// &lt;returns&gt;是否是闰年&lt;/returns&gt;
public static bool IsRun(int year)
{
    bool b = (year % 400 == 0) || (year % 4 == 0 &amp;&amp; year % 100 != 0);
    return b;
}
</code></pre><ul>
<li><strong>注意</strong>: <em>&quot;并非所有的代码路径都返回值&quot;</em> 的语法错误对应的情况是: 声明了返回值的类型但没有返回任何值</li>
</ul>
<h2 id="方法的概念">方法的概念</h2>
<ul>
<li>实参: 在传参时, 实实在在<strong>存在</strong>的参数</li>
<li>形参: 在方法中使用的<strong>形式上</strong>的参数, 作用域只在其方法内部</li>
<li>两者关系: 作用域不同, 没有必然的练习, 只有数据类型要求一致, 且两者<strong>都在内存中开辟空间</strong></li>
</ul>
<h2 id="练习2">练习2</h2>
<ul>
<li>读取输入的整数, 如果输入是数字, 则返回, 否则提示用户重新输入</li>
</ul>
<pre tabindex="0"><code>while (true)
{
    Console.WriteLine(&#34;请输入数字&#34;);

    try
    {
        int number = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine(number);
        break;
    }
    catch
    {
        Console.WriteLine(&#34;输入有误&#34;);
    }
}
Console.ReadKey();
</code></pre><ul>
<li>典型错误</li>
</ul>
<pre tabindex="0"><code>Main(){
    NewMethod();
    Console.ReadKey();
}
</code></pre><blockquote>
<p>原则: <strong>方法的功能一定要单一</strong>
忌讳: <strong>方法中出现<u>提示用户输入</u>的字眼</strong></p>
<blockquote>
<p>否则, 这就限定了这个方法只能在控制台程序中使用<br>
而其他程序开发将不兼容<br>
团队合作中也很讨厌</p>
</blockquote>
</blockquote>
<ul>
<li>正确事例</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    Console.WriteLine(&#34;请输入一个整数&#34;);
    Console.WriteLine(GetNumber(Console.ReadLine()));
    Console.ReadKey();

}

/// &lt;summary&gt;
/// 判断用户的输入是否是数字
/// 是数字就返回
/// 不是, 就提示用户重新输入
/// &lt;/summary&gt;
public static int GetNumber(string s)
{
    while (true)
    {
        try
        {
            int number = Convert.ToInt32(s);
            return number;
        }
        catch
        {
            Console.WriteLine(&#34;请重新输入&#34;);
            s = Console.ReadLine();
        }
    }
}
</code></pre><h2 id="两个练习">两个练习</h2>
<ul>
<li>只允许输入y和n, 用方法实现</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    // 方法的效果, 只输入y或n, 只要不是, 重新输入

    Console.WriteLine(&#34;请输入y或者n&#34;);
    Console.WriteLine(IsYesOrNo(Console.ReadLine()));
    Console.ReadKey();

}
/// &lt;summary&gt;
/// 限定用户只能输入yes或者no
/// &lt;/summary&gt;
/// &lt;param name=&#34;input&#34;&gt;用户的输入&lt;/param&gt;
/// &lt;returns&gt;&#34;y&#34;或者&#34;n&#34;&lt;/returns&gt;
public static string IsYesOrNo(string input)
{
    while (true)
    {
        if (input == &#34;y&#34; || input == &#34;n&#34;)
        {
            return input;
        }
        else
        {
            Console.WriteLine(&#34;只能输入y或者n, 请重新输入&#34;);
            input = Console.ReadLine();
        }
    }
}
</code></pre><ul>
<li>计算输入数组的总和</li>
</ul>
<pre tabindex="0"><code>static void Main(string[] args) //Main函数
{  //代码从这里走起
    int[] numbers = { 1, 2, 3, 4, 5, 6 };
    Console.WriteLine(GetSum(numbers));
}
/// &lt;summary&gt;
/// 输入整数数组, 返回其总和
/// &lt;/summary&gt;
/// &lt;param name=&#34;numbers&#34;&gt;数组&lt;/param&gt;
/// &lt;returns&gt;总和&lt;/returns&gt;
public static int GetSum(int[] numbers)
{
    int sum = 0;
    for (int i = 0; i &lt; numbers.Length; i++)
    {
        sum += numbers[i];
    }
    return sum;
}
</code></pre>]]></content>
		</item>
		
		<item>
			<title>Day15_方法</title>
			<link>https://zhydada.github.io/posts/day15_%E6%96%B9%E6%B3%95___2022-08-06_23-17/</link>
			<pubDate>Sat, 06 Aug 2022 23:17:16 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day15_%E6%96%B9%E6%B3%95___2022-08-06_23-17/</guid>
			<description>方法 细节问题 (课程第五天)总结 方法 定义: 方法(函数)就是将一堆代码重用的机制 语法: [public] static 返回值类型 方法名 ([参数列表]) { 方法体; } 说明 public: 访问</description>
			<content type="html"><![CDATA[<ul>
<li><a href="#%E6%96%B9%E6%B3%95">方法</a></li>
<li><a href="#%E7%BB%86%E8%8A%82%E9%97%AE%E9%A2%98">细节问题</a></li>
<li><a href="#%E8%AF%BE%E7%A8%8B%E7%AC%AC%E4%BA%94%E5%A4%A9%E6%80%BB%E7%BB%93">(课程第五天)总结</a></li>
</ul>
<hr>
<h2 id="方法">方法</h2>
<ul>
<li>定义: <strong>方法</strong>(函数)就是将一堆代码重用的机制</li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>[public] static 返回值类型 方法名 ([参数列表])
{
    方法体;
}
</code></pre><ul>
<li>
<p>说明</p>
<ul>
<li><em><strong>public</strong></em>: 访问修饰符</li>
<li><em><strong>static</strong></em>: 静态的</li>
<li><strong>返回值</strong>: 如果没有, 写void</li>
<li><strong>方法名</strong>: Pascal</li>
<li><strong>参数列表</strong>: 完成方法必要的条件, 没参数也不可以省略小括号</li>
</ul>
</li>
<li>
<p><strong>注意:</strong> 自定义方法同<code>Main</code>方法同级, 应当写在<code>Main</code>之外</p>
</li>
<li>
<p>补充: <em><strong>return</strong></em>两个作用:</p>
<ul>
<li>可以直接停止并跳出当前的方法</li>
<li>返回方法的返回值</li>
</ul>
</li>
<li>
<p>e.g.1 计算两个整数之间的最大值</p>
</li>
</ul>
<pre tabindex="0"><code>class Class1
{
    static void Main(string[] args) //Main函数
    {  //代码从这里走起

        int n1 = 2;
        int n2 = 999;
        Console.WriteLine(Class1.GetMax(n1, n2));

    }

    /// &lt;summary&gt;
    /// 计算两个整数的最大值  
    /// &lt;/summary&gt;
    /// &lt;param name=&#34;n1&#34;&gt;第一个整数&lt;/param&gt;
    /// &lt;param name=&#34;n2&#34;&gt;第二个整数&lt;/param&gt;
    /// &lt;returns&gt;两者中的最大值&lt;/returns&gt;
    public static int GetMax(int n1,int n2)
    {
        return n1 &gt; n2 ? n1 : n2;
    }
}
</code></pre><blockquote>
<p>注意: 要学会写<strong>简单易懂</strong>的文档注释
<em>引用</em>方法的时候要记得写为<code>类名.方法名</code></p>
</blockquote>
<h2 id="细节问题">细节问题</h2>
<ul>
<li>写方法的过程, 先要想清楚<strong>参数</strong>, 至于返回值可以<em>稍后修改</em></li>
<li>方法提示的左上角提示<strong>返回值的类型</strong></li>
<li>在某些情况下, 类名是可以省略的, 如果写的方法和<code>Main函数</code>在同一个类中, 就可以省略</li>
</ul>
<h2 id="课程第五天总结">(课程第五天)总结</h2>
<ul>
<li>常量: 一旦赋值, 不能重新赋值</li>
<li>枚举: 规范开发</li>
<li>结构: 为了一次性声明多个不同类型的变量
<ul>
<li>字段: 多个值</li>
</ul>
</li>
<li>数组
<ul>
<li>一次性存储多个相同类型的变量</li>
<li>通过下标(索引)访问元素</li>
<li>数组的取值和赋值</li>
<li>数组长度一旦声明不可改变</li>
<li>冒泡排序(<code>Array.Sort()</code>和<code>Array.Reverse()</code>)</li>
</ul>
</li>
<li>方法
<ul>
<li>写方法</li>
<li>调用方法</li>
<li>参数</li>
<li>返回值</li>
<li><em><strong>return</strong></em></li>
</ul>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day14_数组的操作</title>
			<link>https://zhydada.github.io/posts/day14_%E6%95%B0%E7%BB%84%E7%9A%84%E6%93%8D%E4%BD%9C___2022-08-05_22-55/</link>
			<pubDate>Fri, 05 Aug 2022 22:55:44 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day14_%E6%95%B0%E7%BB%84%E7%9A%84%E6%93%8D%E4%BD%9C___2022-08-05_22-55/</guid>
			<description>计算数组的最大值/最小值/总和/平均值 翻转数组 冒泡排序 计算数组的最大值/最小值/总和/平均值 随机长度, 随机值组成的整数数组 int[] nums = { 1, 2, 3, 4, 5,</description>
			<content type="html"><![CDATA[<ul>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%95%B0%E7%BB%84%E7%9A%84%E6%9C%80%E5%A4%A7%E5%80%BC%E6%9C%80%E5%B0%8F%E5%80%BC%E6%80%BB%E5%92%8C%E5%B9%B3%E5%9D%87%E5%80%BC">计算数组的最大值/最小值/总和/平均值</a></li>
<li><a href="#%E7%BF%BB%E8%BD%AC%E6%95%B0%E7%BB%84">翻转数组</a></li>
<li><a href="#%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F">冒泡排序</a></li>
</ul>
<h2 id="计算数组的最大值最小值总和平均值">计算数组的最大值/最小值/总和/平均值</h2>
<ul>
<li>随机长度, 随机值组成的整数数组</li>
</ul>
<pre tabindex="0"><code>int[] nums = { 1, 2, 3, 4, 5, 6, -7, 8, 9, 90 };
int max = nums[0];
max = int.MinValue;
int min = nums[0];
min = int.MaxValue;
int sum = 0;
for (int i = 0; i &lt; nums.Length; i++)
{
    if (nums[i] &gt;= max)
    {
        max = nums[i];
    }
    if (nums[i] &lt;= min)
    {
        min = nums[i];
    }
    sum += nums[i];
}
Console.WriteLine(&#34;数组的\n最大值是{0}\n最小值是{1}\n总和是{2}\n平均数是{3}&#34;, max, min, sum, sum / nums.Length);
</code></pre><blockquote>
<p>给<code>max</code> <code>int</code>中的最小值, 给<code>min</code> <code>int</code>中的最大值<br>
但是这不如赋值数组中的一项来的简单直接</p>
</blockquote>
<h2 id="翻转数组">翻转数组</h2>
<ul>
<li>将每个元素倒序排列</li>
</ul>
<blockquote>
<p>思路: 头尾互换, 交换次数是N/2, 例如5个数换2次</p>
</blockquote>
<pre tabindex="0"><code>string[] s = { &#34;我&#34;, &#34;是&#34;, &#34;好人&#34;, &#34;;&#34;, &#34;精&#34;, &#34;英&#34;, &#34;计&#34;, &#34;划&#34; };
for (int i = 0; i &lt; s.Length / 2; i++)
{
    string temp = s[i];
    s[i] = s[s.Length - 1 - i];
    s[s.Length - 1 - i] = temp;
}
for (int i = 0; i &lt; s.Length; i++)
{
    Console.Write(s[i]);
}
Console.ReadKey();
</code></pre><h2 id="冒泡排序">冒泡排序</h2>
<ul>
<li>将数组中的元素按大小排序</li>
<li>过程: 依次和后面的元素比较, 只要大于就交换一次</li>
</ul>
<blockquote>
<p>将[5,4,3,2,1,0]升序排序</p>
</blockquote>
<table>
<thead>
<tr>
<th style="text-align:center">比较的次数</th>
<th style="text-align:center">与之比较的数</th>
<th style="text-align:center">交换的次数</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">第1次</td>
<td style="text-align:center">4,3,2,1,0</td>
<td style="text-align:center">5</td>
</tr>
<tr>
<td style="text-align:center">第2次</td>
<td style="text-align:center">3,2,1,0,5</td>
<td style="text-align:center">4</td>
</tr>
<tr>
<td style="text-align:center">第3次</td>
<td style="text-align:center">2,1,0,4,5</td>
<td style="text-align:center">3</td>
</tr>
<tr>
<td style="text-align:center">第4次</td>
<td style="text-align:center">1,0,3,4,5</td>
<td style="text-align:center">2</td>
</tr>
<tr>
<td style="text-align:center">第5次</td>
<td style="text-align:center">1,2,3,4,5</td>
<td style="text-align:center">1</td>
</tr>
</tbody>
</table>
<pre tabindex="0"><code>int[] nums = { 5, 4, 3, 2, 1, 0 }; 
for (int i = 0; i &lt; nums.Length-1; i++) //控制比较的次数, 六个数比5次, Length-1=5
{
    for (int j = 0; j &lt; nums.Length-1-i; j++)   //控制每次比较中交换的次数, 枚举找规律
    {
        if (nums[j] &gt; nums[j + 1])
        {
            int temp = nums[j + 1];
            nums[j + 1] = nums[j];
            nums[j] = temp;
        }
    }
}
for (int i = 0; i &lt; nums.Length; i++)
{
    Console.Write(nums[i]);
}
</code></pre><blockquote>
<p>相当于每次都把前面的i-1个数中最大的拉到最右边, 故一定可以排序</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day_13_数组</title>
			<link>https://zhydada.github.io/posts/day13_%E6%95%B0%E7%BB%84___2022-08-04_23-11/</link>
			<pubDate>Thu, 04 Aug 2022 23:11:18 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day13_%E6%95%B0%E7%BB%84___2022-08-04_23-11/</guid>
			<description>数组的定义 数组的定义 一次性存储多个相同类型的变量 语法 //法1 数组类型[] 数组名 = new 数组类型[数组长度] int[] nums1 = new int[10]; //法2 int[] nums2 = {1,2,3}; //法3 int[] nums3</description>
			<content type="html"><![CDATA[<ul>
<li><a href="#%E6%95%B0%E7%BB%84%E7%9A%84%E5%AE%9A%E4%B9%89">数组的定义</a></li>
</ul>
<h2 id="数组的定义">数组的定义</h2>
<ul>
<li>一次性存储多个<strong>相同类型</strong>的变量</li>
<li>语法</li>
</ul>
<pre tabindex="0"><code>//法1
数组类型[] 数组名 = new 数组类型[数组长度]
int[] nums1 = new int[10];
//法2
int[] nums2 = {1,2,3};
//法3
int[] nums3 = new int[3]{1,2,3};
//法4
int[] nums3 = new int[]{1,2,3};
</code></pre><ul>
<li>
<p>说明:</p>
<ul>
<li>声明数组时, 在内存中, 给每个元素赋予<strong>初始值</strong>(<em>占内存</em>)</li>
<li>开辟多少内存空间取决于数组长度, 每一块空间称之为数组的一个<strong>元素</strong></li>
<li>每个元素的标号称为下标或<strong>索引</strong>(<em>访问</em>的依据)</li>
<li>索引由<code>0</code>开始, 数组的最后一个元素的索引为<code>数组长度-1</code></li>
<li>索引超出数组界限会抛异常!</li>
<li><strong>数组长度一旦被声明就不再改变</strong></li>
</ul>
</li>
<li>
<p>不同数据类型对应的初始值</p>
</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">数据类型</th>
<th style="text-align:center">默认初始值</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">int</td>
<td style="text-align:center">0</td>
</tr>
<tr>
<td style="text-align:center">string</td>
<td style="text-align:center">null</td>
</tr>
<tr>
<td style="text-align:center">bool</td>
<td style="text-align:center">false</td>
</tr>
</tbody>
</table>
]]></content>
		</item>
		
		<item>
			<title>Day12_复杂数据类型_常量_枚举_结构</title>
			<link>https://zhydada.github.io/posts/day12_%E5%A4%8D%E6%9D%82%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B_%E5%B8%B8%E9%87%8F_%E6%9E%9A%E4%B8%BE_%E7%BB%93%E6%9E%84___2022-08-03_21-48/</link>
			<pubDate>Wed, 03 Aug 2022 21:48:48 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/day12_%E5%A4%8D%E6%9D%82%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B_%E5%B8%B8%E9%87%8F_%E6%9E%9A%E4%B8%BE_%E7%BB%93%E6%9E%84___2022-08-03_21-48/</guid>
			<description>主要内容 小复习 常量 枚举 结构 小复习 常见变量类型 int/double/string/char/bool/decimal 变量使用规则: 声明$\rightarrow$赋值$\rightarrow$使用 命名规则 Camel 和 Pascal 运</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>小复习</li>
<li>常量</li>
<li>枚举</li>
<li>结构</li>
</ul>
<hr>
<h2 id="小复习">小复习</h2>
<ul>
<li>
<p>常见变量类型</p>
<ul>
<li>int/double/string/char/bool/decimal</li>
</ul>
</li>
<li>
<p>变量使用规则:</p>
<ul>
<li>声明$\rightarrow$赋值$\rightarrow$使用</li>
</ul>
</li>
<li>
<p>命名规则</p>
<ul>
<li>Camel 和 Pascal</li>
</ul>
</li>
<li>
<p>运算符</p>
<ul>
<li>赋值: =</li>
<li>复合赋值: += -= *= /= %=</li>
<li>算数: + - * / % ++ &ndash;</li>
<li>关系: &gt; &lt; &gt;= &lt;= == !=</li>
<li>逻辑: &amp;&amp; || !</li>
</ul>
</li>
<li>
<p>语法结构</p>
<ul>
<li>分支结构: if if-else</li>
<li>选择结构: while do-while for</li>
</ul>
</li>
</ul>
<h2 id="常量">常量</h2>
<ul>
<li>区别于变量, <strong>常量</strong>是恒定的值, <strong>不能被重新赋值</strong></li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>const 数据类型 常量名称 = 初始赋值; 
</code></pre><ul>
<li>特点:
<ul>
<li><strong>不能被重新赋值</strong></li>
</ul>
</li>
</ul>
<h2 id="枚举">枚举</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>[public] enum 枚举名
{
    值1,
    值2,
    ...
} 
</code></pre><ul>
<li>
<p>语法解释</p>
<ul>
<li>[]中括号代表可以省略(别把中括号写出来!)</li>
<li><em><strong>public</strong></em>是<strong>访问修饰符</strong>. public是权限最高(或者也可以说是没有权限), 任何地方都可以访问(与private相对比)</li>
<li><em><strong>enum</strong></em>是关键字, 用于声明枚举(其缩写为 <em>Enumerate</em>)</li>
<li><em><strong>枚举名</strong></em>要符合<em><strong>Pascal</strong></em><em>命名规范</em></li>
</ul>
</li>
<li>
<p>意义</p>
</li>
</ul>
<blockquote>
<p>例如学员管理时, 要定义性别<br>
不同程序员命名时, 可能出现如下情况</p>
<blockquote>
<p>char gender = &lsquo;男&rsquo;;<br>
string s1 = &ldquo;female&rdquo;;<br>
bool b = true;</p>
</blockquote>
<p>为了统一样式, 可以将枚举声明在 <strong>命名空间内 &amp; 类的外面</strong><br>
使得所有的类都是用统一的<em>变量类型</em></p>
</blockquote>
<ul>
<li>
<p>特点:</p>
<ul>
<li><em><strong>enum</strong></em>同int等<strong>变量类型</strong>一致, 都是用于存储数据</li>
<li>区别仅在于变量的<em>使用方式</em></li>
<li>相当于自定义一种变量类型</li>
<li>注意是<strong>点(.)</strong> 出来的</li>
</ul>
</li>
<li>
<p>实例</p>
</li>
</ul>
<pre tabindex="0"><code>namespace NAME
{
    public enum Seasons
    {
        春,
        夏,
        秋,
        冬
    }

    class class1
    {
        static ... Main ...
        {
            Season thisMonth = Seasons.夏
            // 最后输出的就是&#34;夏&#34;
        }
    }
}
</code></pre><h2 id="枚举类型和intstring类型之间的转换">枚举类型和<em><strong>int/string</strong></em>类型之间的转换</h2>
<ul>
<li>枚举类型<strong>默认</strong>可以和<em><strong>int</strong></em>类型互相转换</li>
<li>即, 两者<strong>兼容</strong></li>
</ul>
<pre tabindex="0"><code>public enum QQstate
{
    OnLine,
    OffLine,
    Leave = 9,
    Busy,
    QMe
}
</code></pre><ul>
<li>枚举类型转换int类型</li>
</ul>
<pre tabindex="0"><code>QQstate state = QQstate.OnLine;
int n = (int)state//隐式转换
Console.WriteLine(n);
Console.WriteLine((int)QQstate.OffLine);
Console.WriteLine((int)QQstate.Leave);
Console.WriteLine((int)QQstate.Busy);
Console.WriteLine((int)QQstate.QMe);
</code></pre><blockquote>
<p>结果为<br>
0 1 9 10 11</p>
</blockquote>
<ul>
<li>int转换枚举类型</li>
</ul>
<pre tabindex="0"><code>int n1 = 1
QQstate state = (QQstate)n1;
Console.WriteLine(state);
Console.WriteLine((QQstate)8);
</code></pre><blockquote>
<p>结果为<br>
OffLine 8<br>
注意隐式失败不报错</p>
</blockquote>
<ul>
<li>
<p><strong>注意:</strong> 所有类型都能转为<em><strong>string</strong></em>类型</p>
</li>
<li>
<p>调用<code>.toString()</code>就可以</p>
</li>
<li>
<p>字符串<em><strong>string</strong></em>转换为<strong>枚举类型</strong>较为麻烦</p>
</li>
<li>
<p>因为<strong>两者不兼容</strong></p>
</li>
<li>
<p>此时应当调用<code>Enum.parse(string1)</code></p>
</li>
</ul>
<pre tabindex="0"><code>string s1 = &#34;3&#34;;
string s2 = &#34;夏&#34;;
string s3 = &#34;99&#34;;
string s4 = &#34;夏天&#34;;
Season month1 = (Season)Enum.Parse(typeof(Season), s1);
Season month2 = (Season)Enum.Parse(typeof(Season), s2);
Season month3 = (Season)Enum.Parse(typeof(Season), s3);
Season month4 = (Season)Enum.Parse(typeof(Season), s4);
Console.WriteLine(month1);
Console.WriteLine(month2);
Console.WriteLine(month3);
Console.WriteLine(month4);
</code></pre><blockquote>
<p>结果很amazing<br>
1: 冬<br>
2: 夏<br>
3: 99<br>
4: 抛异常</p>
</blockquote>
<ul>
<li><strong>注意:</strong> 数字不能转换返回数字本身; 文本不对应就会抛异常</li>
</ul>
<h2 id="结构">结构</h2>
<blockquote>
<p>大学管理系统<br>
要求数据: 姓名 性别 年龄 年级<br>
问题是: 需要上千个变量</p>
</blockquote>
<ul>
<li>意义: 结构可以一次性声明<strong>多个变量</strong></li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>[public] struct 结构名
{
  成员;//可以理解为变量
}
</code></pre><ul>
<li><strong>注意:</strong> 放置的位置和枚举<em><strong>enum</strong></em>一样</li>
<li>举例:</li>
</ul>
<pre tabindex="0"><code>public struct Person
{
  public string _name;//成为字段
  public int _age;
  public char _gender;
}
</code></pre><pre tabindex="0"><code>Person zsPerson;
zsPerson._name = &#34;张三&#34;;
zsPerson._age = 21;
zsPerson._gender = &#39;男&#39;;

Person lsPerson;
lsPerson._name = &#34;李四&#34;;
lsPerson._age = 22;
lsPerson._gender = &#39;男&#39;;
</code></pre><blockquote>
<p>即 面向对象 编程(现在只能说很类似)</p>
</blockquote>
<ul>
<li><strong>字段</strong> 与 <strong>变量</strong> 最本质的区别
<ul>
<li><strong>变量</strong>在程序运行的过程中, 只能存放一个值</li>
<li><strong>字段</strong>可以存储多个值</li>
</ul>
</li>
<li><strong>注意:</strong> 字段命名时一定记得加<strong>下划线</strong></li>
</ul>
<h2 id="练习">练习</h2>
<ul>
<li>给定一个叫MyColor的结构, 包含三个int成员red, blue, green</li>
<li>声明一个MyColor类型的变量, 为其成员赋值, 使之表示红色</li>
</ul>
<pre tabindex="0"><code>public struct Mycolor
{
    public int _red;
    public int _green;
    public int _blue;
}
class Class1
{
    static void Main(string[] args) 
    {  //代码从这里走起

        Mycolor mc;
        mc._red = 255;
        mc._green = 0;
        mc._blue = 0;

    }
}
</code></pre><blockquote>
<p>感想: 看似复杂无意义, 实际上是为了规范而发明的<br>
当所有成员的代码组合起来的时候, 规范才有了意义<br>
团队是合作的, 而非个人solo</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>2048</title>
			<link>https://zhydada.github.io/posts/2048/</link>
			<pubDate>Tue, 02 Aug 2022 23:05:34 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/2048/</guid>
			<description>游戏入口 务必使用电脑pc端, 点我开始游戏 手机端入口, 但目前只能玩经典模式, 触控按钮隐藏在图示的四个标红区域 操作提示: 按K键可以展示每个按键对</description>
			<content type="html"><![CDATA[<h1 id="游戏入口">游戏入口</h1>
<ul>
<li>务必使用电脑pc端, 点我<a href="http://zhydada.github.io/2048/game/">开始游戏</a></li>
<li>手机端<a href="http://zhydada.github.io/2048/mobile/">入口</a>, 但目前只能玩经典模式, 触控按钮隐藏在图示的四个标红区域</li>
<li>操作提示: 按K键可以展示每个按键对应的功能, 空格键对应的就是经典模式
<img src="http://zhydada.github.io/2048/screen-shot/show.png" alt=""></li>
</ul>
<h2 id="简介">简介</h2>
<ul>
<li>内容: 高中阶段制作的一款2048游戏, 共6个模式</li>
<li>灵感: 背景泡泡来源于一个<del>不那么正规的</del>网址(还是不展示了, 侵删)<br>
计时器的来源:</li>
<li>特色: 6大特色模式
0. 经典模式: 忠实原味
<img src="http://zhydada.github.io/2048/screen-shot/0.png" alt="">
<ol>
<li>暗黑竞速模式: 限速20秒
<img src="http://zhydada.github.io/2048/screen-shot/1.png" alt=""></li>
<li>火红双倍模式: 每次移动会生成两个新数字
<img src="http://zhydada.github.io/2048/screen-shot/2.png" alt=""></li>
<li>X方块挑战模式: X方块对应着-64, 不消掉会卡位置, 两个X会合并为一个X, 但这样会扣128分
<img src="http://zhydada.github.io/2048/screen-shot/3.png" alt=""></li>
<li>万宁模式: 每动一次, 所有数字翻倍! 但最多不超过8192, 纯粹娱乐
<img src="http://zhydada.github.io/2048/screen-shot/4.png" alt=""></li>
<li>混沌模式: 各种方块(包括1,X,也有可能不生成)都有可能生成, 每一次移动后所有数字向右移动一格, 最右侧的那一列移动到最左边
<img src="http://zhydada.github.io/2048/screen-shot/5.png" alt=""></li>
</ol>
</li>
</ul>
<h2 id="备注">备注:</h2>
<ol>
<li>在这个期间攻破了DeepCopy这一核心技术, 搞清楚了存储空间的原理</li>
<li>竞速模式刚做完, 班上就掀起了一股浪潮, 全名挑战最高分<br>
令我高兴的是, 大家都很尽兴; 令我伤心的是, 我的蓝牙键盘的方向键直接被按得报废了&hellip;😂</li>
</ol>
<h2 id="历代版本说明">历代版本说明:</h2>
<ul>
<li>V1&ndash;隐藏式触控按钮(在V4被遮挡)</li>
<li>V2&ndash;高分榜</li>
<li>V3&ndash;新增两个游戏模式<br>
&ndash;暗黑竞速模式<br>
&ndash;火红双倍模式<br>
&ndash;X方块挑战模式</li>
<li>V4&ndash;加入动画制作<br>
&ndash;背景方块泡泡<br>
&ndash;开头展示动画</li>
<li>V5&ndash;实现从外部读取设置</li>
<li>V6&ndash;竞速模式限制按键频率</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Tetris</title>
			<link>https://zhydada.github.io/posts/tetris/</link>
			<pubDate>Tue, 02 Aug 2022 21:53:31 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/tetris/</guid>
			<description>游戏入口 务必使用电脑pc端, 点我开始游戏 可能需要手动调整界面的缩放 简介 内容: 高中阶段制作的一款俄罗斯方块游戏, 稍加改编, 共有三种模式可供选择</description>
			<content type="html"><![CDATA[<h1 id="游戏入口">游戏入口</h1>
<ul>
<li>务必使用电脑pc端, 点我<a href="http://zhydada.github.io/Tetris/game/">开始游戏</a></li>
<li>可能需要手动调整界面的缩放</li>
</ul>
<h2 id="简介">简介</h2>
<ul>
<li>内容: 高中阶段制作的一款俄罗斯方块游戏, 稍加改编, 共有三种模式可供选择.</li>
<li>灵感: 来自本人在日本旅行期间扭蛋得到的<em>俄罗斯方块掌中游戏机</em>, 里面约有20种俄罗斯方块的模式, 虽然大多相似, 但启发我创造了一些可以实际操作的模式<br>
无论如何, 这对于练习js还是很有帮助的<br>
原本的思路是照抄网上的canvas, 但在弄清原理后自己用<strong>HTML</strong>实现了, 效果还不赖(p.s.网格都是一个个独立的div, 所以即便是缩放的操作也不会走样)<br>
背景的动效来源于一个脚本: <a href="https://www.jb51.net/jiaoben/446998.html">jQuery+HTML5+Canvas实现四色3D多边形背景动画特效源码</a><br>
班上的wcx同学十分喜欢这个游戏, 对原本刺眼的配色提出了建设性建议, <em>thanks</em>!</li>
<li>特色: 柔和配色 / 险象环生的难度梯度 / 三种模式 / 高分榜 / GM模式(官方开挂)
<ul>
<li>增强模式: 加入了5个方块组成的<em>异形</em>
<img src="http://zhydada.github.io/Tetris/screen-shots/2.png" alt=""></li>
<li>混沌模式: 开局随机生成灰色方块
<img src="http://zhydada.github.io/Tetris/screen-shots/3.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="历代版本说明">历代版本说明</h2>
<ul>
<li>
<p>硬件</p>
<ol>
<li>操作优化(运动暂停;Wall Kick)</li>
<li>分数</li>
<li>下一个Tetris</li>
<li>突破性技术:localStorage向数据丢失说拜拜!可持久保持玩家最高分记录!</li>
<li>加强模式:出现5连块</li>
<li>障碍模式:开局黑色块</li>
<li>实现分段提速&amp;理想的Alerter提示板</li>
<li>实现操作2度提升,按住一直移动</li>
<li>应对每个模式的不同storage(应该放在start里做,切换模式即显示)</li>
</ol>
</li>
<li>
<p>软装</p>
<ol>
<li>基础框架搭建(背景大小合适化;版面布局)</li>
<li>现实footer注解,字号排版调整布局</li>
<li>hsl色号平衡调整</li>
<li>仿FRVR护眼配色</li>
</ol>
</li>
<li>
<p>待优化</p>
<ol>
<li>新mode</li>
<li>玩家名称&amp;技能</li>
<li>全版面像素风格化</li>
</ol>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Jumpin Ball V1</title>
			<link>https://zhydada.github.io/posts/jumpin-ball-v1/</link>
			<pubDate>Mon, 01 Aug 2022 21:33:53 +0800</pubDate>
			
			<guid>https://zhydada.github.io/posts/jumpin-ball-v1/</guid>
			<description>游戏入口 务必使用电脑pc端, 点我开始游戏 简介 名称: 高中阶段制作的一款横版跳跃游戏, 游戏名来自jc同学, 中文名暂且称为&amp;quot;横版跳跃&amp;q</description>
			<content type="html"><![CDATA[<h1 id="游戏入口">游戏入口</h1>
<ul>
<li>务必使用电脑pc端, 点我<a href="http://zhydada.github.io/Jumpin-Ball-V1/game/">开始游戏</a></li>
</ul>
<h2 id="简介">简介</h2>
<ul>
<li>名称: 高中阶段制作的一款横版跳跃游戏, 游戏名来自jc同学, 中文名暂且称为&quot;横版跳跃&quot;.</li>
<li>灵感: 来源于一个脚本: <a href="https://www.jb51.net/jiaoben/619838.html">激流勇进</a><br>
就连主题配色也没改动, 纯粹出于喜欢2D platform平台跳跃类游戏, 自己不断扩充制作而成.</li>
<li>特色: 过关提升 / iwanna-like / 平台跳跃 / 彩蛋 / 中偏高难度</li>
</ul>
<h2 id="备注">备注:</h2>
<ol>
<li>bug还是有点的, 速度太快容易穿墙</li>
<li><strong>纯属娱乐</strong>, 由于核心代码<em>照搬</em>了原脚本, 侵权速删</li>
<li>存档信息使用了LocalStorage, 只要了解点js就可以畅玩</li>
<li>必须使用电脑游玩</li>
<li>现在的版本算下来是<strong>V6.20.5</strong>, 大版本是<em>一丁目</em>, 想玩历史版本可以联系我</li>
</ol>
<h2 id="历代版本说明">历代版本说明:</h2>
<ul>
<li>
<p>硬件</p>
<ol>
<li>原版引擎</li>
<li>二段跳制作</li>
<li>制作了更多关卡以及关卡之间的切换</li>
<li>游戏存档技术</li>
<li>消除大量bug</li>
<li>格式规范化,量产准备已完善</li>
<li>彩蛋准备工作完成</li>
<li>存档机制修复</li>
<li>滑翔技能实现</li>
<li>掉落死亡和踩红死亡计数</li>
<li>制作了第三第四关</li>
<li>会移动的机关,trapClock计数系统</li>
<li>深度复制!突破技术壁垒!</li>
<li>制作了第五关</li>
<li>存档机制修复pro: 不会改变原来的重生点</li>
<li>制作了反重力领域技能</li>
<li>制作了第六关</li>
<li>完善所有关卡的成就</li>
<li>收尾工作(三成就)</li>
<li>检查并完善所有BUG</li>
</ol>
</li>
<li>
<p>软装</p>
<ol>
<li>居中视图</li>
<li>操作和按键的文字提示</li>
<li>配色方案</li>
<li>全屏尽享</li>
<li>系列故事/解密元素已加入</li>
</ol>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day11_类型转换和方法简介_更多的习题_三元表达式</title>
			<link>https://zhydada.github.io/posts/day11_%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%92%8C%E6%96%B9%E6%B3%95%E7%AE%80%E4%BB%8B_%E6%9B%B4%E5%A4%9A%E7%9A%84%E4%B9%A0%E9%A2%98_%E4%B8%89%E5%85%83%E8%A1%A8%E8%BE%BE%E5%BC%8F___2022-07-30_21-36/</link>
			<pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day11_%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E5%92%8C%E6%96%B9%E6%B3%95%E7%AE%80%E4%BB%8B_%E6%9B%B4%E5%A4%9A%E7%9A%84%E4%B9%A0%E9%A2%98_%E4%B8%89%E5%85%83%E8%A1%A8%E8%BE%BE%E5%BC%8F___2022-07-30_21-36/</guid>
			<description>主要内容 类型转换 循环的习题 随机数 类型转换 使用Convert.Int32(&amp;quot;string&amp;quot;), 失败了会抛异常 使用int.P</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>类型转换</li>
<li>循环的习题</li>
<li>随机数</li>
</ul>
<hr>
<h2 id="类型转换">类型转换</h2>
<ul>
<li>使用<code>Convert.Int32(&quot;string&quot;)</code>, 失败了会抛异常</li>
<li>使用<code>int.Parse(&quot;string&quot;)</code>效果一致</li>
</ul>
<blockquote>
<p>事实上, 前者就是调用后者, 因此后者<strong>效率更高</strong>(但可以忽略不计)</p>
</blockquote>
<ul>
<li><code>int.TryParse(&quot;string&quot;)</code></li>
</ul>
<pre tabindex="0"><code>int number1 = 10;
int number2 = 10;
bool a = int.TryParse(&#34;123&#34;, out number1);
bool b = int.TryParse(&#34;123abc&#34;, out number2);
Console.WriteLine(a);
Console.WriteLine(number1);
Console.WriteLine(b);
Console.WriteLine(number2);
Console.ReadLine();

&gt;&gt;&gt; True
&gt;&gt;&gt; 123
&gt;&gt;&gt; False
&gt;&gt;&gt; 0
</code></pre><ul>
<li>作用:
<ul>
<li>转换成功, 返回值是True, 转换结果输出给number</li>
<li>转换失败, 返回值是False, 将0输出给number</li>
</ul>
</li>
</ul>
<h2 id="循环的习题">循环的习题</h2>
<ul>
<li>录入五个人的年龄并计算平均年龄<br>
输入数据出现负数或者大于100, 立刻停止并报错</li>
</ul>
<pre tabindex="0"><code>int sum = 0;
bool b = true;
for (int i = 0; i &lt; 5; i++)
{
    Console.WriteLine(&#34;输入第{0}个人的年龄&#34;, i + 1);
    try
    {
        int age = Convert.ToInt32(Console.ReadLine());
        if (age &gt;= 0 &amp;&amp; age &lt;= 100)
        {
            sum += age;
        }
        else
        {
            Console.WriteLine(&#34;输入的数据不在正确范围内, 程序退出&#34;);
            b = false;
            break;
        }
    }//try
    catch
    {
        Console.WriteLine(&#34;输入的不是年龄, 程序退出&#34;);
        b = false;
        break;
    }
}

if (b)
{
    Console.WriteLine(&#34;5个人的平均年龄是{0}&#34;, sum / 5);
}
Console.ReadKey();
</code></pre><h2 id="三元表达式">三元表达式</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>表达式1 ? 表达式2 : 表达式3 
</code></pre><ul>
<li>说明:
<ul>
<li>表达式1 一般是个<strong>关系表达式</strong></li>
<li>表达式1是true, 则整个表达式就是表达式2的类型</li>
<li>表达式1是false, 则整个表达式就是表达式3的类型</li>
</ul>
</li>
<li>注意: 表达式2,3的数据类型<strong>必须一致</strong></li>
</ul>
<h2 id="随机数">随机数</h2>
<ol>
<li>创建能产生随机数的对象</li>
</ol>
<pre tabindex="0"><code>Random r = new Random(); 
</code></pre><ol start="2">
<li>调用方法</li>
</ol>
<pre tabindex="0"><code>int rNumber = r.Next(1,10);
</code></pre>]]></content>
		</item>
		
		<item>
			<title>Day10_continue和for</title>
			<link>https://zhydada.github.io/posts/day10_continue%E5%92%8Cfor___2022-07-26_22-48/</link>
			<pubDate>Tue, 26 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day10_continue%E5%92%8Cfor___2022-07-26_22-48/</guid>
			<description>主要内容 关键字 Continue for 循环(和嵌套) 程序调试 关键字 Continue 作用: 立刻结束本次循环 判断循环的条件 成立继续, 不成立退出 注意: 凡是continue后面的代码</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>关键字 <em><strong>Continue</strong></em></li>
<li><em><strong>for</strong></em> 循环(和嵌套)</li>
<li>程序调试</li>
</ul>
<hr>
<h2 id="关键字-continue">关键字 <em><strong>Continue</strong></em></h2>
<ul>
<li>
<p>作用:</p>
<ol>
<li>立刻结束本次循环</li>
<li>判断循环的条件</li>
<li>成立继续, 不成立退出</li>
</ol>
</li>
<li>
<p><strong>注意:</strong> 凡是continue<strong>后面的代码</strong>不会被访问到<br>
如果<em>循环变量</em>i++在循环最后, 一定要考虑到</p>
</li>
<li>
<p>练习: 找出100内所有质数</p>
</li>
</ul>
<pre tabindex="0"><code>int i = 2;

while (i &lt;= 100)
{
    //让i和比i小的(或者说i的一半)全部取余一遍, 有整除就continue
    int j = 2;
    bool b = true;
    while (j &lt;= (i / 2))
    {
        if (i % j == 0)
        {
            b = false;
            break;
        }
        j++;
    }
    if (b)
    {
        Console.WriteLine(i);
    }
    i++;
}
Console.ReadKey();
</code></pre><blockquote>
<p>自己写的时候错了两次, 一定要记得<strong>i++和j++</strong></p>
</blockquote>
<h2 id="for-循环"><em><strong>for</strong></em> 循环</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>for (int i = 0; i &lt; length; i++)
{
  循环体
}
</code></pre><ul>
<li>
<p>for后面的三个表达式:</p>
<ul>
<li>声明循环变量, 记录循环次数</li>
<li>循环条件</li>
<li>改变循环的条件, 使循环条件会不成立</li>
</ul>
</li>
<li>
<p><strong>特点:</strong> 一般用于知道循环<strong>次数</strong>的循环</p>
</li>
<li>
<p>补充: 小窍门, for加<kbd>tab</kbd>两次可以跳出框架片段<br>
打forr可以跳出逆向循环的片段</p>
</li>
</ul>
<h2 id="练习">练习</h2>
<ul>
<li>求水仙花数</li>
</ul>
<pre tabindex="0"><code>for (int i = 100; i &lt;= 999; i++)
{
    int a = i / 100;
    int b = i % 100 / 10;
    int c = i % 10;
    if (a * a * a + b * b * b + c * c * c == i)
    {
        Console.WriteLine(i);
    }
}
Console.ReadKey();
</code></pre><ul>
<li>输出加法表</li>
</ul>
<pre tabindex="0"><code>Console.WriteLine(&#34;输入正整数&#34;);
int number = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i &lt;= number; i++)
{
    Console.WriteLine(&#34;{0}+{1}={2}&#34;, i, number - i, number);
}
Console.ReadKey();
</code></pre><blockquote>
<p><em><strong>try-catch</strong></em>用户的输入是个<strong>好习惯</strong>(虽然但是懒得这么做orz)</p>
</blockquote>
<h2 id="for循环的嵌套"><em><strong>for</strong></em>循环的嵌套</h2>
<ul>
<li>打印九九乘法表</li>
</ul>
<pre tabindex="0"><code>for (int i = 1; i &lt; 10; i++)
{
    for (int j = 1; j &lt;= i; j++)
    {
        Console.Write(&#34;{0}x{1}={2}\t&#34;, i, j, i * j);
    }
    Console.Write(&#34;\n&#34;);
}
Console.ReadKey();
</code></pre><blockquote>
<p><code>Console.Write()</code>用来表示接着前面打印<br>
<code>Console.WriteLine()</code><strong>相当于</strong><code>Console.Write(&quot;xxx\n&quot;)</code></p>
</blockquote>
<hr>
<h2 id="程序调试">程序调试</h2>
<ul>
<li>
<p>功能:</p>
<ul>
<li>写完代码, 想看一下执行的过程</li>
<li>写完程序, 发现没有按照预期执行</li>
</ul>
</li>
<li>
<p>方法:</p>
<ul>
<li><kbd>F11</kbd> 逐行 单步调试</li>
<li><kbd>F10</kbd> 逐过程调试</li>
<li>断点调试</li>
</ul>
</li>
<li>
<p>监视窗口: <em>红色的值</em>代表<strong>刚刚发生变化</strong></p>
</li>
<li>
<p>断点: 在最左侧灰色位置<strong>设置断点</strong><br>
如果选中了一行代码, 可以按快捷键<kbd>F9</kbd></p>
</li>
<li>
<p><strong>注意:</strong> <em>黄色箭头</em>是指<strong>将要执行但还没有执行的代码</strong></p>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day09_while和break</title>
			<link>https://zhydada.github.io/posts/day09_while%E5%92%8Cbreak___2022-07-24_21-10/</link>
			<pubDate>Sun, 24 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day09_while%E5%92%8Cbreak___2022-07-24_21-10/</guid>
			<description>主要内容 循环结构 while 关键字 break 练习*3 do-while 结构 循环结构 while while循环: while(循环条件) { 循环体 } 执行过程: 循环运行到while处 首先判断循</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>循环结构 while</li>
<li>关键字 break</li>
<li>练习*3</li>
<li>do-while 结构</li>
</ul>
<hr>
<h2 id="循环结构-while">循环结构 while</h2>
<ul>
<li><em><strong>while</strong></em>循环:</li>
</ul>
<pre tabindex="0"><code>while(循环条件)
{
    循环体
}
</code></pre><ul>
<li>执行过程:
<ol>
<li>循环运行到while处</li>
<li>首先判断循环条件是否成立</li>
<li>成立(即 返回true), 执行循环体</li>
<li>执行一遍, 返回1步骤</li>
<li>一旦不成立, 跳出while循环</li>
</ol>
</li>
<li>一般总有一行代码, 能够改变循环条件, 使条件不再成立</li>
<li>循环条件永远成立的循环, 称之为 <em>&quot;死循环&quot;</em></li>
</ul>
<blockquote>
<p>一定要分析出来 <strong>循环体</strong> 和 <strong>循环条件</strong><br>
琢磨一遍, 写在注释里, 养成思考的习惯!</p>
</blockquote>
<h2 id="关键字break的用法">关键字<em><strong>break</strong></em>的用法</h2>
<ul>
<li>
<p><strong>作用:</strong></p>
<ul>
<li>跳出<em><strong>switch-case</strong></em>结构</li>
<li>跳出当前的<em><strong>while</strong></em>循环</li>
</ul>
</li>
<li>
<p><strong>特点:</strong> 一般不单独使用, 配合if使用</p>
</li>
</ul>
<h2 id="小练习3">小练习*3</h2>
<ul>
<li>练习1: 输入班级总人数, 依次输入学员的成绩, 计算平均成绩和总成绩</li>
</ul>
<pre tabindex="0"><code>bool b = true;
//避免出现异常就退出, 设置大循环
while (b) {

    //输入班级总人数, 依次输入学员的成绩, 计算平均成绩和总成绩
    //循环体: 接收成绩, 累加成绩
    //循环条件: 循环次数小于总人数

    //声明变量
    int number = 0;
    int i = 0;
    double sum = 0;

    //接收总人数
    Console.WriteLine(&#34;输入班级总人数(正整数)&#34;);
    try
    {
        number = Convert.ToInt32(Console.ReadLine());

        if (number &gt; 0)
        {
            try
            {
                //按总人数展开循环, 依次接收成绩累加
                while (i &lt; number)
                {
                    Console.WriteLine(&#34;请输入第{0}位学员的成绩&#34;, ++i);
                    sum += Convert.ToDouble(Console.ReadLine());
                }

                Console.WriteLine(&#34;这个班级总共{0}位学员\n总成绩是{1}\n平均成绩是{2:0.00}&#34;, number, sum, sum / number);
                b = false;  //这行代码能够运行就意味着程序生效, 退出循环

            }   //输入成绩不符合要求的try 结束括号
            catch
            {
                Console.WriteLine(&#34;成绩输入不符合规范, 程序退出&#34;);
            }
        }   //判断number是正数的结束括号
        else
        {
            Console.WriteLine(&#34;人数应当是正整数, 程序退出&#34;);
        }

    }   //这是try number接收的结束括号
    catch
    {
        Console.WriteLine(&#34;成绩输入不符合要求, 程序退出&#34;);
    }   //这是catch number接收的结束括号

    if (b)  //如果bool还是true, 就说明最终结果还未出现, 那么提示程序重启
    {
        Console.WriteLine(&#34;=========\n程序重启, 请认真填写\n再也没有什么嘻嘻哈哈了\n=========&#34;);
    }

}   //这里是最外圈的循环结束括号
Console.ReadKey();
</code></pre><blockquote>
<p>**注意:**做题时, 先分析出来所需要的变量, <strong>提前声明</strong>, 免得作用域出错<br>
注: 以上代码是自己写的</p>
</blockquote>
<ul>
<li>练习2: 老师问:&ldquo;这道题你会做了吗?&rdquo; 回答y, 就放学; 回答n, 就再讲一遍, 再问一遍.
<ul>
<li>一直到学生回答y才放学</li>
<li>直到学生会or讲了5遍还不会, 都要放学</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>//循环体: 老师提问, 学生回答, 老师讲题
//循环的两个条件: 学生不会 且 讲的次数小于5遍

string answer = &#34;&#34;;
int i = 0;

while (answer != &#34;y&#34; &amp;&amp; i &lt; 10)
{
    Console.WriteLine(&#34;这是我第{0}遍给你讲题, 你会了么?(y/n)&#34;, ++i);
    answer = Console.ReadLine();

    //如果回答是 就跳出循环
    if (answer == &#34;y&#34;)
    {
        Console.WriteLine(&#34;会了就放学吧!&#34;);
        break;
    }
    else if (i == 5)    //第五次还不会就放学
    {
        Console.WriteLine(&#34;讲了5遍还不会也没必要讲了, 还是放学吧!&#34;);
        break;
    }
}

Console.ReadKey(); 
</code></pre><blockquote>
<p>暂时不考虑非常严谨的异常处理</p>
</blockquote>
<ul>
<li>练习3: 2006年 学员80000人, 每年增长25%, 问哪一年人数达到20万人?</li>
</ul>
<pre tabindex="0"><code>//循环体: 人数每年增长25%
//循环条件: 人数&lt;20万

double people = 80000;
int year = 2006;
while (people &lt; 200000)
{
    people *= 1.25;
    year++;
}
Console.WriteLine(&#34;到{0}年时, 人数达到20w&#34;, year);
Console.ReadKey(); 
</code></pre><blockquote>
<p>简单数学, 所以数学功底要扎实</p>
</blockquote>
<hr>
<h2 id="do-while-结构"><em><strong>do-while</strong></em> 结构</h2>
<ul>
<li><strong>语法:</strong></li>
</ul>
<pre tabindex="0"><code>do
{
    循环体
}while(循环条件);
</code></pre><ul>
<li>
<p><strong>执行过程:</strong></p>
<ol>
<li>首先执行一遍循环体</li>
<li>拿着执行结果 去判断循环条件</li>
<li>如果成立, 继续执行do中循环体</li>
<li>不成立就跳出循环</li>
</ol>
</li>
<li>
<p><strong>特点:</strong> 先循环, 再判断; <strong>至少执行一次</strong></p>
</li>
</ul>
<blockquote>
<p><strong>注意:</strong> while后面带有封号</p>
</blockquote>
<h2 id="小练习">小练习</h2>
<ul>
<li>练习: 不断输入学生姓名, 输入q结束</li>
</ul>
<pre tabindex="0"><code>string name = &#34;&#34;;
do
{
    Console.WriteLine(&#34;输入姓名, 输入q结束&#34;);
    name = Console.ReadLine();
} while (name != &#34;q&#34;);        

Console.ReadKey();
</code></pre><ul>
<li>题目: 不断要求用户输入一个数字(假定均是正整数), 用户输入end时, 显示刚才输入的数字中最大的数字</li>
</ul>
<pre tabindex="0"><code>string input = &#34;&#34;;
int max = 0;
while (input != &#34;end&#34;)
{
    Console.WriteLine(&#34;输入正整数, 若输入end将显示最大值&#34;);
    input = Console.ReadLine();
    if (input != &#34;end&#34;)
    {
        try
        {
            int number = Convert.ToInt32(input);
            //打擂台
            if (number &gt; max)
            {
                max = number;
            }
        }
        catch
        {
            Console.WriteLine(&#34;输入不符合规范, 重新输入&#34;);
        }
    }
    else    //end
    {
        Console.WriteLine(&#34;最大值是{0}&#34;, max);
    }
}
Console.ReadKey();
</code></pre>]]></content>
		</item>
		
		<item>
			<title>Day08_异常捕获_switch-case结构</title>
			<link>https://zhydada.github.io/posts/day08_%E5%BC%82%E5%B8%B8%E6%8D%95%E8%8E%B7_switch-case%E7%BB%93%E6%9E%84___2022-07-23_22-42/</link>
			<pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day08_%E5%BC%82%E5%B8%B8%E6%8D%95%E8%8E%B7_switch-case%E7%BB%93%E6%9E%84___2022-07-23_22-42/</guid>
			<description>主要内容 异常捕获 异常捕获 异常: 语法上没有错误, 在程序运行过程中, 由于某些原因程序出了问题, 不能再正常运行 出现异常很正常, 当我们知道程序中有可</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>异常捕获</li>
</ul>
<hr>
<h2 id="异常捕获">异常捕获</h2>
<ul>
<li><strong>异常:</strong> 语法上没有错误, 在程序运行过程中, 由于某些原因程序出了问题, 不能再正常运行</li>
<li>出现异常很正常, 当我们知道程序中有可能出现异常时<br>
为了让程序更加<em>坚强</em>一些(不容易出现异常), 应当在程序中经常性地使用<em><strong>try-catch</strong></em>来进行<strong>异常捕获</strong></li>
</ul>
<blockquote>
<p>哪行代码有可能出现异常, 就<strong>踹(try)他一脚</strong></p>
</blockquote>
<pre tabindex="0"><code>try
{
    有可能会出现异常的代码
}
catch
{
    出现异常时运行的代码
}
</code></pre><ul>
<li><strong>执行过程:</strong> try中的代码没有异常, 那么catch中的代码不会执行;<br>
如果catch中出现异常, 那么后面的代码全部不运行, 直接跳到catch中执行代码</li>
</ul>
<blockquote>
<p>记得多用异常捕获, 让异常和没异常一样</p>
</blockquote>
<h2 id="变量的作用域">变量的作用域</h2>
<ul>
<li><strong>变量的作用域</strong>就是变量能使用的范围</li>
<li><strong>变量的作用域</strong>一般从<em>声明变量的那一行</em>开始, 一直到声明所在的花括号对应的<em>结束花括号</em>结束</li>
<li>在变量的作用域的范围之内, 我们可以访问并使用变量, 超出这个范围就访问不到了</li>
</ul>
<h2 id="switch-case-结构">switch-case 结构</h2>
<ul>
<li><em><strong>swich-case</strong></em>用来处理<strong>多条件</strong>的<strong>定值</strong>的判断</li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>switch(变量或表达式的 值)
{
    case 值1: 要执行的代码;
    break;
    case 值2: 要执行的代码;
    break;
    case 值3: 要执行的代码;
    break;
    default: 要执行的代码;
    break;
}
</code></pre><ul>
<li>
<p>执行过程:</p>
<ol>
<li>先计算 变量或表达式的 值</li>
<li>拿这个返回的值依次和每个case后面带的值进行匹配</li>
<li>匹配成功就执行该case的代码</li>
<li>执行完成遇到break跳出该结构</li>
<li>如果均不匹配, 就看是否有default</li>
<li>如果有default, 就执行该代码</li>
<li>如果没有, 无事发生</li>
</ol>
</li>
<li>
<p><strong>注意:</strong> <em>case后面的值</em> 和 <em>switch的变量</em> 的<strong>类型要一致</strong></p>
</li>
</ul>
<h2 id="练习">练习</h2>
<ul>
<li>题目1: &gt;=90 A档; [80,90) B档; &hellip;&lt;60E档; 用switch-case做</li>
</ul>
<pre tabindex="0"><code>Console.WriteLine(&#34;请输入考试成绩(100以内的正整数)&#34;);
int score = Convert.ToInt32(Console.ReadLine());
switch (score / 10)
{
    case 10:
    case 9:
        Console.WriteLine(&#34;A&#34;);
        break;
    case 8:
        Console.WriteLine(&#34;B&#34;);
        break;
    case 7:
        Console.WriteLine(&#34;C&#34;);
        break;
    case 6:
        Console.WriteLine(&#34;D&#34;);
        break;
    default:
        Console.WriteLine(&#34;E&#34;);
        break;
}
Console.ReadKey();
</code></pre><blockquote>
<p><strong>注意:</strong> case 10和case 9后的代码<strong>完全一样</strong>, 因此可以简写</p>
</blockquote>
<ul>
<li>题目2: 请用户输入年份 和 月份, 输出该月的天数(结合闰年)</li>
</ul>
<pre tabindex="0"><code>//接收
Console.WriteLine(&#34;请输入一个年份&#34;);
try
{
    int year = Convert.ToInt32(Console.ReadLine());
    Console.WriteLine(&#34;请输入一个月份&#34;);
    try
    {
        int month = Convert.ToInt32(Console.ReadLine());// 可能性 1-12

        //声明变量
        int day = 0;

        if (month &gt;= 1 &amp;&amp; month &lt;= 12)
        {

            switch (month)
            {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    day = 31;
                    break;
                case 2:
                    //有平年闰年之分
                    bool b = (year % 400 == 0) || (year % 4 == 0 &amp;&amp; year % 100 != 0);
                    if (b)
                    {
                        day = 29;
                    }
                    else
                    {
                        day = 28;
                    }
                    break;
                default:
                    day = 30;
                    break;
            } //switch的括号

            Console.WriteLine(&#34;{0}年{1}月有{2}天&#34;, year, month, day);
        } //if判断的括号
        else
        {
            Console.WriteLine(&#34;输入月份不符合要求, 程序退出&#34;);
        }
    } //try月份的括号
    catch //和月份的try配对
    {
        Console.WriteLine(&#34;输入月份有误, 程序退出&#34;);
    }

} //try年份的括号
catch //和年份的try配对
{
    Console.WriteLine(&#34;输入的年份有误, 程序退出&#34;);
}
Console.ReadKey();
</code></pre><blockquote>
<p><strong>总结&amp;反思</strong><br>
写代码的时候切忌: <strong>不要边写边想异常</strong>, 这样只会乱套<br>
全篇写完, 正常功能运行成功, 再回头做异常处理<br>
全局考虑异常</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day07_if结构</title>
			<link>https://zhydada.github.io/posts/day07_if%E7%BB%93%E6%9E%84___2022-07-22_16-35/</link>
			<pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day07_if%E7%BB%93%E6%9E%84___2022-07-22_16-35/</guid>
			<description>主要内容 判断闰年小练习 基本程序结构前瞻 if / else / else if 四个分支结构练习 判断闰年小练习 Console.WriteLine(&amp;#34;请输入要判断的</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>判断闰年小练习</li>
<li>基本程序结构前瞻</li>
<li>if / else / else if</li>
<li>四个分支结构练习</li>
</ul>
<hr>
<h2 id="判断闰年小练习">判断闰年小练习</h2>
<pre tabindex="0"><code>Console.WriteLine(&#34;请输入要判断的年份&#34;);
int year = Convert.ToInt32(Console.ReadLine());
//闰年的两个条件:
//1. 能被400整除
//2. 能被4整除, 但不能被100整除

bool b = (year % 400 == 0) || (year % 4 == 0 &amp;&amp; year % 100 != 0);
Console.WriteLine(b);
Console.ReadKey();
</code></pre><blockquote>
<p><em>逻辑与</em>的优先级 <strong>大于</strong> <em>逻辑或</em></p>
</blockquote>
<blockquote>
<p><em>逻辑与</em>也可以用一个&quot;&amp;&ldquo;的符号<br>
区别在于:</p>
<blockquote>
<p>两个&rdquo;&amp;&ldquo;如果遇到一个false, 之后的表达式就不再判断</p>
</blockquote>
<blockquote>
<p>一个&rdquo;&amp;&ldquo;会把所有表达式全部判断一遍</p>
</blockquote>
<p>结论是, 两个的效率更高, 推荐使用(<em>逻辑或</em>同理)</p>
</blockquote>
<h2 id="结构">结构</h2>
<ul>
<li>顺序结构: 程序从Main函数进入, 从上至下一行一行地执行, 不会跳行</li>
<li>分支结构: if if-else</li>
<li>选择结构: if else-if switvh-case</li>
<li>循环结构: while do-while for foreach</li>
<li>&hellip;</li>
</ul>
<h2 id="if结构">if结构</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>if(判断条件){
   要执行的代码;
}
</code></pre><ul>
<li>判断条件: 一般为<em>关系表达式</em> 或 <em>布尔类型的值</em></li>
<li>执行过程: 执行到if处, 首先判断括号中的判断条件
<ul>
<li>若成立(即返回True), 则执行if后接的大括号中的代码</li>
<li>若不成立(即返回False), 则跳过if后接的大括号中的代码, 继续向下执行</li>
</ul>
</li>
<li>特点: 先判断, 再选择性执行代码</li>
<li><strong>注意:</strong> 花括号外不加封号&rdquo;;&quot;</li>
</ul>
<h2 id="if-else-结构">if-else 结构</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>if(判断条件成立){
   条件满足时执行的代码;
}else{
   条件不满足时执行的代码
}
</code></pre><ul>
<li>特点: 先判断再执行, 选择其中一块代码执行</li>
<li><strong>注意:</strong> <em><strong>else</strong></em>只和最近的<em><strong>if</strong></em>的配对</li>
</ul>
<h2 id="if-else-if-结构">if else-if 结构</h2>
<ul>
<li>作用: 用来处理<strong>多条件</strong>的<strong>区间性</strong>的判断<br>
(之后的switch是处理<strong>多条件</strong>的<strong>定值性</strong>的判断)</li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>if(判断条件){
   要执行的代码;
}else if(判断条件){
   要执行的代码
}else if(判断条件){
   要执行的代码
}else if(判断条件){
   要执行的代码
}else{
   要执行的代码
}
</code></pre><ul>
<li>特点: 只要有一个条件成立了, 就进入分支运行代码, 没有就执行<em>else</em>, 最后跳出结构</li>
</ul>
<hr>
<h1 id="四个练习">四个练习</h1>
<h2 id="练习1">练习1</h2>
<ul>
<li>三个数字找最大</li>
</ul>
<pre tabindex="0"><code>//获取三个数字
Console.WriteLine(&#34;请输入第一个数字&#34;);
double n1 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine(&#34;请输入第二个数字&#34;);
double n2 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine(&#34;请输入第三个数字&#34;);
double n3 = Convert.ToDouble(Console.ReadLine());

//1和2比
if (n1 &gt; n2)//1&gt;2
{
      if (n1 &gt; n3)//1&gt;3
      {
         Console.WriteLine(n1);
      }
      else//3&gt;1&gt;2
      {
         Console.WriteLine(n3);
      }
}
else//2&gt;1
{
      if (n3 &gt; n2)//3&gt;2&gt;1
      {
         Console.WriteLine(n3);
      }
      else//2&gt;3 2&gt;1
      {
         Console.WriteLine(n2);
      }
}
Console.ReadKey();
</code></pre><blockquote>
<p>要学会写注释, 这对以后的大项目很有帮助</p>
</blockquote>
<h2 id="练习2">练习2</h2>
<ul>
<li>输密码, 如果是88888就提示正确, 如果错误提示再输一遍, 二次输入正确提示正确, 二次输入错误就提示错误</li>
</ul>
<pre tabindex="0"><code>Console.WriteLine(&#34;请输入密码&#34;);
string pwd = Console.ReadLine();
if (pwd == &#34;88888&#34;)
{
      Console.WriteLine(&#34;登陆成功&#34;);
}
else//输入错误再次输入
{
      Console.WriteLine(&#34;密码错误, 请重新输入密码&#34;);
      pwd = Console.ReadLine();
      if(pwd == &#34;88888&#34;)
      {
         Console.WriteLine(&#34;搞死了, 终于正确了, 登陆成功&#34;);
      }
      else
      {
         Console.WriteLine(&#34;两次输入都错误, 程序结束&#34;);
      }
}
Console.ReadKey();
</code></pre><h2 id="练习3">练习3</h2>
<ul>
<li>分别输入用户名和密码, admin 和 88888, 如果都对就登陆成功<br>
如果用户名错就提示用户名不存在<br>
用户名正确密码错也要提示</li>
</ul>
<pre tabindex="0"><code>//接收信息
Console.WriteLine(&#34;输入用户名&#34;);
string name = Console.ReadLine();
Console.WriteLine(&#34;输入密码&#34;);
string pwd = Console.ReadLine();

//第一种情况 都正确
if (name == &#34;admin&#34; &amp;&amp; pwd == &#34;88888&#34;)
{
      Console.WriteLine(&#34;登陆成功&#34;);
}
else if (name == &#34;admin&#34;) //密码错
{
      Console.WriteLine(&#34;密码错误&#34;);
}
else
{
      Console.WriteLine(&#34;用户名错误或不存在&#34;);
}
Console.ReadKey();
</code></pre><blockquote>
<p>用!=会方便一些</p>
</blockquote>
<h2 id="练习4">练习4</h2>
<ul>
<li>询问用户年龄, 如果大于等于18, 提示可以查看<br>
如果大于等于10并且小于18, 询问是否继续查看(yes or no)<br>
用户输yes就提示继续查看, 否则提示放弃查看</li>
</ul>
<pre tabindex="0"><code>//接收信息
Console.WriteLine(&#34;请问年龄&#34;);
int age = Convert.ToInt32(Console.ReadLine());
if (age &gt;= 18)
{
      Console.WriteLine(&#34;看吧, 早晚要知道的&#34;);
}
else if (age &lt; 10)
{
      Console.WriteLine(&#34;滚蛋, 回家吃奶去&#34;);
}
else
{
      Console.WriteLine(&#34;确定要看么?(yes/no)&#34;);
      string input = Console.ReadLine();
      if (input == &#34;yes&#34;)
      {
         Console.WriteLine(&#34;看吧, 后果自负&#34;);
      }
      else
      {
         Console.WriteLine(&#34;乖孩子, 回家吃奶去&#34;);
      }
}
Console.ReadKey();
</code></pre><blockquote>
<p>车门焊死</p>
</blockquote>
<hr>
<h1 id="小贴士">小贴士</h1>
<ul>
<li>整个程序最后如果太多花括号就会看不清<br>
要记住, <strong>倒数第三个花括号</strong>是Main函数的花括号, 代码在那里截止</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day06_Convert类型转换_加加减减_关系运算与逻辑判断</title>
			<link>https://zhydada.github.io/posts/day06_convert%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2_%E5%8A%A0%E5%8A%A0%E5%87%8F%E5%87%8F_%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97%E4%B8%8E%E9%80%BB%E8%BE%91%E5%88%A4%E6%96%AD___2022-07-21_15-50/</link>
			<pubDate>Thu, 21 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day06_convert%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2_%E5%8A%A0%E5%8A%A0%E5%87%8F%E5%87%8F_%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97%E4%B8%8E%E9%80%BB%E8%BE%91%E5%88%A4%E6%96%AD___2022-07-21_15-50/</guid>
			<description>主要内容 Convert类型转换 加加减减 运算顺序 复合赋值运算符 关系运算符 逻辑运算符 Convert类型转换 Convert转换工厂可以使得不兼容的</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>Convert类型转换</li>
<li>加加减减</li>
<li>运算顺序</li>
<li>复合赋值运算符</li>
<li>关系运算符</li>
<li>逻辑运算符</li>
</ul>
<hr>
<h2 id="convert类型转换">Convert类型转换</h2>
<ul>
<li>Convert转换工厂可以使得不兼容的两种类型(e.g.string和int)进行转换</li>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>double double1 = Convert.ToDouble(string1);
int int1 = Convert.ToInt32(string2);//32是指位数
</code></pre><ul>
<li>条件: <strong>面上</strong>要过得去</li>
</ul>
<blockquote>
<p>如果上两个例子中string2=&ldquo;123abc&quot;就会<em>报错</em>, 即语法正确, 但程序错误无法继续</p>
</blockquote>
<pre tabindex="0"><code>//练习: 让用户输入姓名和大三门成绩, 输出姓名和平均分
Console.WriteLine(&#34;姓名?&#34;);
string name = Console.ReadLine();
Console.WriteLine(&#34;语文?&#34;);
string strChinese = Console.ReadLine();
Console.WriteLine(&#34;数学?&#34;);
string strMath = Console.ReadLine();
Console.WriteLine(&#34;英语?&#34;);
string strEnglish = Console.ReadLine();
//注意变量的命名规范
double chinese = Convert.ToDouble(strChinese);
double math = Convert.ToDouble(strMath);
double english = Convert.ToDouble(strEnglish);

Console.WriteLine(&#34;你叫:{0}, 三门的总成绩是{1}, 平均分是{2:0.0}&#34;, name, (chinese+math+english), (chinese+math+english)/3);
Console.ReadKey();
</code></pre><h2 id="加加减减">加加减减</h2>
<ul>
<li>语法:</li>
</ul>
<pre tabindex="0"><code>int num = 10;
num++;//11
++num;//12
num--;//11
--num;//10
</code></pre><ul>
<li>加加减减分<em>前后</em>, 无论哪一种变量自身结果都会加或减1
<ul>
<li>前置: 先±1, 再参与运算</li>
<li>后置: 先参与运算, 再±1</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>int num = 10;
int result1 = 5 + ++num;
int result2 = 12 + num--;
</code></pre><ul>
<li>上面的事例的效果与下面的代码产生的效果一致</li>
</ul>
<pre tabindex="0"><code>int num = 10;
num = num + 1;
int result1 = 5 + num;
int result2 = 12 + num;
num = num - 1;
</code></pre><pre tabindex="0"><code>int a = 5;
int b = a++ + ++a * 2 + --a + a++;
//a = 5 +1 +1 -1 +1 = 7
//b = 5 + 7*2 + 6 + 6 = 31  
</code></pre><h2 id="运算顺序">运算顺序</h2>
<ul>
<li>对于只需要一个操作数就可以完成的运算符, 称之为<strong>一元运算符</strong><br>
例如: ++ 和 &ndash;</li>
<li>同样地, 两个操作数就是<strong>二元运算符</strong></li>
</ul>
<blockquote>
<p><strong>一元运算符</strong>的优先级高于<strong>二元运算符</strong><br>
从左到右依次运算</p>
</blockquote>
<ul>
<li>上面例子的详细解释如下:</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">步骤</th>
<th style="text-align:center">a的值</th>
<th style="text-align:left">b的值</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">1</td>
<td style="text-align:center">6</td>
<td style="text-align:left">5 + ++a * 2 + &ndash;a + a++</td>
</tr>
<tr>
<td style="text-align:center">2</td>
<td style="text-align:center">7</td>
<td style="text-align:left">5 + 7 * 2 + &ndash;a + a++</td>
</tr>
<tr>
<td style="text-align:center">3</td>
<td style="text-align:center">6</td>
<td style="text-align:left">5 + 7 * 2 + 6 + a++</td>
</tr>
<tr>
<td style="text-align:center">4</td>
<td style="text-align:center">7</td>
<td style="text-align:left">5 + 7 * 2 + 6 + 6</td>
</tr>
<tr>
<td style="text-align:center">5</td>
<td style="text-align:center">7</td>
<td style="text-align:left">31</td>
</tr>
</tbody>
</table>
<h2 id="复合赋值运算符">复合赋值运算符</h2>
<ul>
<li>种类:
<ul>
<li>+=</li>
<li>-=</li>
<li>*=</li>
<li>/=</li>
<li>%=</li>
</ul>
</li>
<li>其实就是运算式的缩写</li>
</ul>
<h2 id="关系运算符">关系运算符</h2>
<ul>
<li><strong>关系运算符</strong>是用来描述两个值之间关系的符号 
由关系运算符连接的表达式称之为<strong>关系表达式</strong>, 结果是布尔类型</li>
<li>种类:
<ul>
<li>&gt; 和 &gt;=</li>
<li>&lt; 和 &lt;=</li>
<li>==</li>
<li>!=</li>
</ul>
</li>
<li>bool类型: 描述对与错, 只有两个值: True 和 False</li>
</ul>
<h2 id="逻辑运算符">逻辑运算符</h2>
<ul>
<li><strong>逻辑运算符</strong>是用来描述两个值之间逻辑关系的符号<br>
由逻辑运算符连接的表达式称之为<strong>逻辑表达式</strong><br>
其两端一般都是 <em>关系表达式</em> 或者 bool类型的值<br>
结果同样也是bool类型的值</li>
<li>类型:
<ul>
<li>&amp;&amp;   逻辑与(btw, 这个的表达式叫做&quot;逻辑与表达式&rdquo;)</li>
<li>||   逻辑或</li>
<li>!    逻辑非</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>//练习: 输入成绩, 做出判断
//语文和数学成绩都大于90, 有一门是大于的
Console.WriteLine(&#34;请输入语文成绩&#34;);
double chinese = Convert.ToDouble(Console.ReadLine());
Console.WriteLine(&#34;请输入数学成绩&#34;);
double math = Convert.ToDouble(Console.ReadLine());

bool a = chinese &gt; 90 &amp;&amp; math &gt; 90;
bool b = chinese &gt; 90 || math &gt; 90;

Console.WriteLine(&#34;两个结果分别是:\n{0}\n{1}&#34;,a,b);
Console.ReadKey();
</code></pre><hr>
<h1 id="小贴士">小贴士</h1>
<ul>
<li>在给<strong>类文件</strong>起名的时候需要注意两点:
<ul>
<li><strong>尽量不要重命名</strong>, 如果该类文件的名称, 代码中的class不会随之改变<br>
这在之后调用的时候会出现问题, 最好的方法还是<em>删除重新创建</em></li>
<li>命名时<strong>不要使用关键字</strong>, 否则对应的关键字将失效</li>
</ul>
</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day05_接受用户输入_基础符号_类型转换</title>
			<link>https://zhydada.github.io/posts/day05_%E6%8E%A5%E5%8F%97%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5_%E5%9F%BA%E7%A1%80%E7%AC%A6%E5%8F%B7_%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2___2022-07-20_13-07/</link>
			<pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day05_%E6%8E%A5%E5%8F%97%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5_%E5%9F%BA%E7%A1%80%E7%AC%A6%E5%8F%B7_%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2___2022-07-20_13-07/</guid>
			<description>主要内容 接受用户输入 转义符 算数运算符 类型转换 接受用户输入 新函数: string str = Console.ReadLine(); 注意: string 可以存储所有的类型, 且要求必须用string来接受 转义符 转义</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>接受用户输入</li>
<li>转义符</li>
<li>算数运算符</li>
<li>类型转换</li>
</ul>
<hr>
<h2 id="接受用户输入">接受用户输入</h2>
<ul>
<li><strong>新函数:</strong> <code>string str = Console.ReadLine();</code></li>
<li><strong>注意:</strong> string 可以存储所有的类型, 且要求必须用string来接受</li>
</ul>
<h2 id="转义符">转义符</h2>
<ul>
<li><strong>转义符</strong>是指一个由一个<em>反斜杠(&quot;\&quot;)<em>和一个</em>特殊字符</em>组成的<strong>一个</strong>具有特殊意义的字符</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">反斜杠后的字符</th>
<th style="text-align:center">效果</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">n</td>
<td style="text-align:center">换行</td>
</tr>
<tr>
<td style="text-align:center">\r\n</td>
<td style="text-align:center">windows系统换行</td>
</tr>
<tr>
<td style="text-align:center">&quot;</td>
<td style="text-align:center">表示双引号</td>
</tr>
<tr>
<td style="text-align:center">t</td>
<td style="text-align:center">等距空格(相当于按Tab键), 多用于排版</td>
</tr>
<tr>
<td style="text-align:center">b</td>
<td style="text-align:center">相当于退格键, 删除前面的一个字符; <strong>但是</strong>放在字符串的最前和最后是没有用的</td>
</tr>
<tr>
<td style="text-align:center">\\</td>
<td style="text-align:center">单纯表示一个\</td>
</tr>
</tbody>
</table>
<ul>
<li>
<p><strong>注意:</strong> \n只能在控制台,Winform和苹果系统中起到作用<br>
若要让windows(比如文本框)识别, 需要使用 \r\n</p>
</li>
<li>
<p><strong>补充:</strong> \起到转义作用时不被视作字符<br>
要让\在字符串中不起到转义的作用, 就在字符串的最前面紧接一个&quot;@&ldquo;符号</p>
</li>
</ul>
<blockquote>
<p>char chara = &lsquo;/b&rsquo;<br>
string path = @&ldquo;D:\path\a\b\c\d\p.avi&rdquo;</p>
</blockquote>
<ul>
<li>&ldquo;@&ldquo;的作用
<ul>
<li>取消\在字符串中的转义作用</li>
<li>将字符串按照编辑的原格式输出</li>
</ul>
</li>
</ul>
<h2 id="算数运算符">算数运算符</h2>
<table>
<thead>
<tr>
<th style="text-align:center">符号</th>
<th style="text-align:center">名称</th>
<th style="text-align:center">举例</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">+</td>
<td style="text-align:center">加</td>
<td style="text-align:center">10+3=&gt;13</td>
</tr>
<tr>
<td style="text-align:center">-</td>
<td style="text-align:center">减</td>
<td style="text-align:center">10-3=&gt;7</td>
</tr>
<tr>
<td style="text-align:center">*</td>
<td style="text-align:center">乘</td>
<td style="text-align:center">10*3=&gt;30</td>
</tr>
<tr>
<td style="text-align:center">/</td>
<td style="text-align:center">除</td>
<td style="text-align:center">10/3=&gt;$3.\dot3$(要看result变量的类型)</td>
</tr>
<tr>
<td style="text-align:center">%</td>
<td style="text-align:center">取余</td>
<td style="text-align:center">10/3=&gt;1</td>
</tr>
</tbody>
</table>
<h2 id="类型转换">类型转换</h2>
<ul>
<li>&ldquo;=&ldquo;作为赋值运算符, 等号两端数据类型<em>必须一致</em><br>
但是, 即便不同也可能不会报错</li>
<li>如果不一致, 当满足下列条件时, 会发生<strong>自动类型转换</strong>(亦称<strong>隐式类型转换</strong>)
<ul>
<li>数据类型兼容, 例如 int和double</li>
<li>目标类型大于源类型, int$\rightarrow$double</li>
</ul>
</li>
</ul>
<blockquote>
<p>如果是int$\rightarrow$double称为<strong>自动/隐式类型转换</strong><br>
如果是double$\rightarrow$int称为<strong>强制/现式类型转换</strong></p>
</blockquote>
<ul>
<li><strong>强制类型转换</strong></li>
<li>条件:
<ul>
<li>两者相兼容</li>
<li>目标类型小于源类型</li>
</ul>
</li>
<li>语法: (目标类型)要转换的值</li>
</ul>
<pre tabindex="0"><code>double d = 2.33;
int n = (int)d;
</code></pre><hr>
<h1 id="补充">补充</h1>
<ul>
<li>整数类型之间的运算的结果<strong>全部</strong>都是整数类型</li>
<li><strong>注意:</strong> 如果操作数中存在一个double类型, 则<strong>整个</strong>运算表达式就被提升为double类型</li>
</ul>
<blockquote>
<p>注意一下这些例子的区别</p>
</blockquote>
<pre tabindex="0"><code>int n1 = 10;
int n2 = 3;
</code></pre><pre tabindex="0"><code>double ans = n1 / n2;
//3
</code></pre><pre tabindex="0"><code>double ans = n1 * 1.0 / n2;
//此时出现一个double操作数
//3.333
</code></pre><pre tabindex="0"><code>double ans = n1 / n2 * 1.0;
//实际上被视作了:
//double ans = (n1 / n2) * 1.0;
//也就是1.0作为一个普通数字投入运算, 由于前面是int, 自动适配类型为int
//3
</code></pre><pre tabindex="0"><code>double ans = n1 / n2 * 1.2;
//实际上被视作了:
//double ans = (n1 / n2) * 1.2;
//此时1.2显然是double, 因此运算式被提升了
//3.599996
</code></pre><pre tabindex="0"><code>double ans = n1 / (n2 * 1.0);
//3.3333
</code></pre><hr>
<h1 id="小知识">小知识</h1>
<ul>
<li>若要使输出保留特定位数的小数点, 则使用以下语法:</li>
</ul>
<pre tabindex="0"><code>Console.WriteLine(&#34;变量ans1保留小数点后三位的输出结果为: {0:0.000}\n同理,四位的话是这样表示: {1:0.0000}&#34;, ans1, ans2);
</code></pre><hr>
<h1 id="小练习">小练习</h1>
<ul>
<li>计算几天(46天)是第几周零几天</li>
<li>107653秒是几天几小时几分钟几秒</li>
<li>可以改为让用户输入</li>
</ul>
<blockquote>
<p>我的答案</p>
</blockquote>
<pre tabindex="0"><code>int days = 46;
int day = days % 7;
int week = days / 7;
Console.WriteLine(&#34;结果是:\n第{0}周\n第{1}天&#34;, week, day);
Console.ReadKey();
</code></pre><pre tabindex="0"><code>int time = 107653;
int day = time / (3600 * 24);
int hour = time % (3600 * 24) / 3600;
int minute = time % 3600 / 60;
int second = time % 60;
Console.WriteLine(&#34;结果是:\n{0}天\n{1}小时\n{2}分钟\n{3}秒&#34;, day, hour, minute, second);
Console.ReadKey();
</code></pre>]]></content>
		</item>
		
		<item>
			<title>Day04_运算符and变量操作</title>
			<link>https://zhydada.github.io/posts/day04_%E8%BF%90%E7%AE%97%E7%AC%A6and%E5%8F%98%E9%87%8F%E6%93%8D%E4%BD%9C___2022-07-19_11-41/</link>
			<pubDate>Tue, 19 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day04_%E8%BF%90%E7%AE%97%E7%AC%A6and%E5%8F%98%E9%87%8F%E6%93%8D%E4%BD%9C___2022-07-19_11-41/</guid>
			<description>主要内容 赋值运算符 加号的使用 占位符 交换两个变量 赋值运算符 &amp;ldquo;=&amp;rdquo; 表示赋值运算符, 负责将右边的值赋值给左边的变量 由&amp;quot;=&amp;ldquo;连接的</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>赋值运算符</li>
<li>加号的使用</li>
<li>占位符</li>
<li>交换两个变量</li>
</ul>
<hr>
<h2 id="赋值运算符">赋值运算符</h2>
<ul>
<li>&ldquo;=&rdquo; 表示<strong>赋值运算符</strong>, 负责将右边的值赋值给左边的变量<br>
由&quot;=&ldquo;连接的表达式称之为<strong>赋值表达式</strong></li>
<li><strong>注意:</strong> 每个表达式都只能求解一个定值</li>
</ul>
<h2 id="加号的使用">加号的使用</h2>
<ul>
<li>起到连接和相加的作用
<ul>
<li>当+的一边有字符串的时候, 起到<strong>连接</strong>的作用</li>
<li>当+的两边都没有有字符串的时候, 起到<strong>相加</strong>的作用</li>
</ul>
</li>
</ul>
<h2 id="占位符">占位符</h2>
<ul>
<li><strong>使用方法:</strong> 先挖坑, 再填个坑</li>
<li>语法格式:
<pre tabindex="0"><code>int n1 = 18;
char n2 = &#34;张&#34;;
string n3 = &#34;鸿尧&#34;;
Console.WriteLine(&#34;我姓{1}, 名{2}, 今年{0}岁了&#34;, n1, n2, n3);
Console.ReadKey();
</code></pre></li>
<li><strong>注意:</strong> 挖几个坑, 就要填几个坑<br>
<strong>但是</strong>, 多填效果一样, 且不会报错<br>
少填就会报错, 出现&quot;异常&rdquo;</li>
</ul>
<blockquote>
<p>&ldquo;异常&quot;是指: 语法上不出现问题, 只不过程序运行期间, 由于某些原因出现问题, 使程序不能再正常的运行</p>
</blockquote>
<blockquote>
<p>可以理解为Bug</p>
</blockquote>
<ul>
<li>还需要注意: 按照挖坑的顺序输出, 即每个占位符对应的顺序</li>
<li>此外: 占位符的数字必须满足 <strong>在0和参数数量之间的整数</strong></li>
</ul>
<h2 id="交换两个变量">交换两个变量</h2>
<ul>
<li><strong>法1:</strong> 第三方</li>
</ul>
<pre tabindex="0"><code>int n1 = 10;
int n2 = 20;

int temp;
temp = n1;
n1 = n2;
n2 = temp;
</code></pre><ul>
<li><strong>法2:</strong> 运算</li>
</ul>
<pre tabindex="0"><code>int n1 = 10;
int n2 = 20;

n1 = n1 - n2;
n2 = n1 + n2;
n1 = n2 - n1;
</code></pre><blockquote>
<p>开发的时候使用 法1<br>
面试的时候使用 法2</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day03_基础语法之注释和变量</title>
			<link>https://zhydada.github.io/posts/day03_%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E4%B9%8B%E6%B3%A8%E9%87%8A%E5%92%8C%E5%8F%98%E9%87%8F___2022-07-17_22-30/</link>
			<pubDate>Sun, 17 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day03_%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E4%B9%8B%E6%B3%A8%E9%87%8A%E5%92%8C%E5%8F%98%E9%87%8F___2022-07-17_22-30/</guid>
			<description>主要内容 写注释 快捷键 变量 变量使用规则 变量起名规矩 写注释 不写注释是流氓 名字瞎起是扯淡 注释的功能 既可以解释代码 也可以注销代码 注释的形式 单行: //xxx 多</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>写注释</li>
<li>快捷键</li>
<li>变量</li>
<li>变量使用规则</li>
<li>变量起名规矩</li>
</ul>
<hr>
<h2 id="写注释">写注释</h2>
<blockquote>
<p>不写注释是流氓
名字瞎起是扯淡</p>
</blockquote>
<ul>
<li>注释的功能
<ul>
<li>既可以解释代码</li>
<li>也可以注销代码</li>
</ul>
</li>
<li>注释的形式
<ul>
<li>单行: //xxx</li>
<li>多行: /* xxx */</li>
<li>文档注释: 在一个方法前面打上///可以直接跳出
<ul>
<li>summary 填写摘要</li>
<li>param 填写每个参数的意义</li>
<li>return 填写返回的值</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><strong>注意:</strong> <strong>代码是写给别人看的!</strong><br>
为了团队工作, 要让别人看起来一目了然</li>
</ul>
<h2 id="常用快捷键">常用快捷键</h2>
<ul>
<li><kbd>Ctrl</kbd>+<kbd>K</kbd>+<kbd>D</kbd>: 快速格式化</li>
<li><kbd>Ctrl</kbd>+<kbd>J</kbd>:  智能提示板</li>
<li><kbd>Ctrl</kbd>+<kbd>K</kbd>+<kbd>C</kbd>: 把所选行转化为注释</li>
<li>在一大段代码的两头写上#region 和 #endregion 可以实现代码的折叠<br>
<strong>备注:</strong> 此外还可以在region的后面加一个空格后 添上解释说明</li>
</ul>
<h2 id="变量">变量</h2>
<ul>
<li><strong>概念:</strong> 变量用来在计算机中存储数据</li>
</ul>
<blockquote>
<p>存数据和客人住酒店很类似</p>
</blockquote>
<ul>
<li>不同的数据存储类型也不同</li>
<li>变量的要求:
<ul>
<li>确定变量类型</li>
<li>给存储空间起<em>有意义</em>的名称, 以便调用</li>
</ul>
</li>
<li>声明变量的语法
<ul>
<li>变量类型 变量名</li>
<li>变量名=值</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>int number;
//官方: 声明了一个int类型的变量
//直白: 在存储空间中开辟了一块能存储整数的空间
number=100;
//官方: 为变量赋值
//直白: 把100放进去
int n=100;//简写
</code></pre><table>
<thead>
<tr>
<th style="text-align:center">变量类型</th>
<th style="text-align:center">中文名</th>
<th style="text-align:center">存储事例</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">int</td>
<td style="text-align:center">整数</td>
<td style="text-align:center">int number=100;</td>
</tr>
<tr>
<td style="text-align:center">long</td>
<td style="text-align:center">长整形</td>
<td style="text-align:center">float f=4.667788f</td>
</tr>
<tr>
<td style="text-align:center">double</td>
<td style="text-align:center">小数</td>
<td style="text-align:center">double s=3.14;  double d=3d;</td>
</tr>
<tr>
<td style="text-align:center">float</td>
<td style="text-align:center">浮点小数</td>
<td style="text-align:center">float f=4.667788f</td>
</tr>
<tr>
<td style="text-align:center">string</td>
<td style="text-align:center">字符串</td>
<td style="text-align:center">string name=&quot;&quot;;</td>
</tr>
<tr>
<td style="text-align:center">char</td>
<td style="text-align:center">单个字符</td>
<td style="text-align:center">char chara=&lsquo;猹&rsquo;;</td>
</tr>
<tr>
<td style="text-align:center">decimal</td>
<td style="text-align:center">货币数据</td>
<td style="text-align:center">decimal money = 250m;</td>
</tr>
</tbody>
</table>
<ul>
<li><strong>注意:</strong> int类型最大区间是[-2^31\ , 2^31]<br>
约为21亿</li>
<li>long的整数范围是$[-2^{32}, 2^{32}-1]$
与int一样只占4个字节, 与int兼容</li>
<li>double类型则是$[\pm5.0\times10^{-324},\pm1.7\times10^{308}]$<br>
精确程度15-16位</li>
<li>float类型为$[-10^{38},10^{38}]$<br>
仅保留小数点后7位, 例如1.234567890会存储为1.2345679</li>
</ul>
<blockquote>
<p><strong>注意:</strong> float是单精度小数, 而double则是双精度小数<br>
float仅占4字节, 而double要占8字节, 因此要合理声明以节约不必要的存储空间</p>
</blockquote>
<ul>
<li>decimal类型为${[-7.9\times10^{28},7.9\times10^{28}]}\over{10^{0-28}}$
精确度28-29位, 适合存储货币, 记得在数据最后加上m或M</li>
<li>char类型不可以存储空, 有且仅有一个字符</li>
</ul>
<hr>
<ul>
<li><strong>补充:</strong> 报错波浪线的意义</li>
</ul>
<blockquote>
<p>红色波浪线: 代码中出现语法错误
绿色波浪线: 也成&quot;警告线&quot;, 有可能会出现错误</p>
</blockquote>
<hr>
<h2 id="变量使用规则">变量使用规则</h2>
<ul>
<li>必须遵循&quot;声明$\rightarrow$赋值$\rightarrow$使用&quot;</li>
</ul>
<h2 id="变量起名规矩">变量起名规矩</h2>
<blockquote>
<p>主要的目的是让阅读代码的人一目了然</p>
</blockquote>
<ul>
<li><em>(现阶段)</em> 必须以字母开头, 不要以数字开头
<ul>
<li>&ldquo;_&ldquo;下划线开头是指面向对象中给类起名时使用</li>
<li>&ldquo;@&ldquo;用以命名保留关键字(如int @int=&ldquo;int&rdquo;)</li>
</ul>
</li>
<li>后面可以跟字母,数字,下划线</li>
<li>C#中大小写是敏感的</li>
<li>变量不可以被重复定义</li>
<li>两种命名规范
<ul>
<li><strong>Camel驼峰命名法:</strong> 第一个单词开头小写, 其余单词首字母大写</li>
<li><strong>Pascal命名法:</strong> 第一个单词开头也要大写, 其余单词首字母大写</li>
</ul>
</li>
</ul>
<blockquote>
<p>前者泛用, 后者用于给<strong>类和Main函数等方法</strong>命名</p>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>Day02_开始使用VisualStudio代码走起</title>
			<link>https://zhydada.github.io/posts/day02_%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8visualstudio%E4%BB%A3%E7%A0%81%E8%B5%B0%E8%B5%B7___2022-07-15_09-52/</link>
			<pubDate>Fri, 15 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day02_%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8visualstudio%E4%BB%A3%E7%A0%81%E8%B5%B0%E8%B5%B7___2022-07-15_09-52/</guid>
			<description>主要内容 安装了vs 熟悉VisualStudio 两行代码 熟悉VisualStudio 解决方案包含多个项目, 项目又包含多个类文件 项目中最要紧的是</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>安装了vs</li>
<li>熟悉VisualStudio</li>
<li>两行代码</li>
</ul>
<hr>
<h2 id="熟悉visualstudio">熟悉VisualStudio</h2>
<ul>
<li><strong>解决方案</strong>包含多个<strong>项目</strong>, 项目又包含多个<strong>类文件</strong></li>
<li>项目中最要紧的是program.cs文件</li>
<li>.cs文件被统称为<strong>类文件</strong></li>
</ul>
<blockquote>
<p><strong>解决方案</strong>就是&quot;公司&quot;<br>
<strong>项目</strong>就是&quot;部门&quot;<br>
<strong>类文件</strong>就是&quot;员工&quot;</p>
</blockquote>
<ul>
<li>代码区</li>
</ul>
<pre tabindex="0"><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//以上是引用命名空间
namespace _01_My_First_Demo //项目名称&amp;命名空间
{
    class Program //被class修饰, 说明是个类
    {
        static void Main(string[] args) //方法or函数 程序的主入口
        {  //代码从这里走起

        }
    }
}
</code></pre><blockquote>
<p>所谓<strong>引用命名空间</strong>其实就是定语</p>
<blockquote>
<p>&ldquo;淘宝&rdquo;=&gt;&ldquo;网上项目&rdquo;=&gt;&ldquo;客户类&rdquo;<br>
&ldquo;京东&rdquo;=&gt;&ldquo;网上项目&rdquo;=&gt;&ldquo;客户类&rdquo;</p>
</blockquote>
<p>其中两个&quot;客户类&quot;毫无关联, 前面的定语就是<strong>引用命名空间</strong></p>
</blockquote>
<blockquote>
<p><strong>方法</strong>就是<strong>函数</strong><br>
<strong>main函数</strong>就是程序的<strong>主入口</strong></p>
</blockquote>
<ul>
<li>在解决方案中
<ul>
<li><strong>.suo</strong>是不可以操作的</li>
<li><strong>.sln</strong>叫做<em>解决方案文件</em>, 包含着解决方案的信息</li>
</ul>
</li>
<li>在项目文件夹中
<ul>
<li><strong>.csproj</strong>是<em>项目文件</em>, 包含项目信息</li>
</ul>
</li>
</ul>
<h2 id="两行代码">两行代码</h2>
<pre tabindex="0"><code>Console.WriteLine(&#34;I&#39;m zhyDaDa&#34;);
Console.ReadKey();
</code></pre><ul>
<li>Console.WriteLine(&ldquo;输出内容&rdquo;);</li>
<li>Console.ReadKey(); 暂停 (约等于bat中的pause)</li>
</ul>
<hr>
<h1 id="总结">总结</h1>
<ul>
<li>大致代码样式get</li>
<li>以及应用命名空间的概念</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day01_了解C井以及.Net的功能</title>
			<link>https://zhydada.github.io/posts/day01_%E4%BA%86%E8%A7%A3c%E4%BA%95%E4%BB%A5%E5%8F%8A.net%E7%9A%84%E5%8A%9F%E8%83%BD___2022-07-14_11-01/</link>
			<pubDate>Thu, 14 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day01_%E4%BA%86%E8%A7%A3c%E4%BA%95%E4%BB%A5%E5%8F%8A.net%E7%9A%84%E5%8A%9F%E8%83%BD___2022-07-14_11-01/</guid>
			<description>p.s. 标题写C井是由于#符号在Url出现会粗问题, 偷懒就先这样将就着了 主要内容 C#编程语言 .Net能做什么 .Net两种交互模式 C#编程语言 C# 是基</description>
			<content type="html"><![CDATA[<h4 id="ps-标题写c井是由于符号在url出现会粗问题-偷懒就先这样将就着了">p.s. 标题写C井是由于#符号在Url出现会粗问题, 偷懒就先这样将就着了</h4>
<h2 id="主要内容">主要内容</h2>
<ul>
<li>C#编程语言</li>
<li>.Net能做什么</li>
<li>.Net两种交互模式</li>
</ul>
<hr>
<h2 id="c编程语言">C#编程语言</h2>
<ul>
<li>C# 是基于 .Net平台 来开发的语言</li>
<li><strong>注意:</strong> JAVA既是一门语言, 同时也是一个平台</li>
<li>.Net平台 也支持其他语言, 不过C#才是主角</li>
</ul>
<h2 id="net能做什么">.Net能做什么</h2>
<table>
<thead>
<tr>
<th style="text-align:center">俗称</th>
<th style="text-align:center">术语</th>
<th style="text-align:center">举例</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">桌面应用程序</td>
<td style="text-align:center">Winform</td>
<td style="text-align:center">微信,QQ</td>
</tr>
<tr>
<td style="text-align:center"><strong>Internet应用程序</strong></td>
<td style="text-align:center">ASP.Net</td>
<td style="text-align:center">携程,CSDN,京东</td>
</tr>
<tr>
<td style="text-align:center">手机开发</td>
<td style="text-align:center">WP8</td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li>关于<strong>Unity3D</strong>的两个发展方向
<ul>
<li>游戏开发</li>
<li>虚拟现实</li>
</ul>
</li>
</ul>
<blockquote>
<p>推荐从虚拟现实转向游戏开发</p>
</blockquote>
<h2 id="net两种交互模式">.Net两种交互模式</h2>
<ul>
<li><strong>C/S</strong>
<ul>
<li>客户端(Client) 和 服务器(Server)</li>
<li>客户端上必须要安装软件</li>
<li>对应Winform桌面应用程序</li>
</ul>
</li>
<li><strong>B/S</strong>
<ul>
<li>浏览器(Browser) 和 服务器(Server)</li>
<li>客户端只需要通过浏览器就可以使用</li>
<li>对应ASP.Net Internet应用程序</li>
</ul>
</li>
</ul>
<hr>
<h1 id="备注">备注</h1>
<ul>
<li>要练打字速度</li>
<li>IDE是指开发工具</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Day00_学习准备与前瞻</title>
			<link>https://zhydada.github.io/posts/day00_%E5%AD%A6%E4%B9%A0%E5%87%86%E5%A4%87%E4%B8%8E%E5%89%8D%E7%9E%BB___2022-07-13_23-32/</link>
			<pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/day00_%E5%AD%A6%E4%B9%A0%E5%87%86%E5%A4%87%E4%B8%8E%E5%89%8D%E7%9E%BB___2022-07-13_23-32/</guid>
			<description>主要内容 学习计划 各语言对比 什么是.Net 学习计划 js仍然要继续使用巩固 首先掌握C# 【01_C#入门到精通】新手强烈推荐：C#开发课程，一整套</description>
			<content type="html"><![CDATA[<h2 id="主要内容">主要内容</h2>
<ul>
<li>学习计划</li>
<li>各语言对比</li>
<li>什么是.Net</li>
</ul>
<hr>
<h2 id="学习计划">学习计划</h2>
<ul>
<li>js仍然要继续使用巩固</li>
<li>首先掌握C#</li>
</ul>
<blockquote>
<p>【01_C#入门到精通】新手强烈推荐：C#开发课程，一整套课程<br>
257集  画质<del>掉渣</del>清晰, 属实老番<br>
视频地址 <a href="https://www.bilibili.com/video/BV1FJ411W7e5">BV1FJ411W7e5</a></p>
<blockquote>
<p>01_C#入门到精通<br>
02_C#数据结构与算法<br>
03_C#上位机编程<br>
04_C#.NET串口通信<br>
05_C#和Unity游戏开发教程<br>
06_C#项目开发与实战</p>
</blockquote>
</blockquote>
<blockquote>
<p>C#零基础入门（C#/NET/零基础/编程/入门/实战教学）B0117<br>
58集 视频地址 <a href="https://www.bilibili.com/video/BV1FL4y1V7HJ">BV1FL4y1V7HJ</a></p>
</blockquote>
<ul>
<li>接着使用Unity3D</li>
<li>.Net/framework会有更多内容</li>
</ul>
<h2 id="语言对比">语言对比</h2>
<ul>
<li>C#是在C++的基础上再一次改进后的编程语言(微软出品)，相比C++而言<strong>难度有所降低</strong></li>
<li>C#侧重于<strong>网络和数据库</strong>编程; C侧重于结构和内存</li>
</ul>
<blockquote>
<p><a href="https://m.imooc.com/wenda/detail/521934">C语言直接与内存打交道，使修改、编辑其他程序与文档变得轻松，简单。</a></p>
</blockquote>
<ul>
<li>C+是一个和C/C++无关的早期编程语言。</li>
<li>C 语言是面向过程的，而 C++ 是<strong>面向对象</strong>的</li>
<li>C#和JS语法上最像</li>
</ul>
<blockquote>
<p><a href="https://www.php.cn/js-tutorial-480187.html">JS的名字和JAVA有多像，语法就和C#有多像</a></p>
</blockquote>
<ul>
<li>TypeScript语言，简称TS语言,TS是包含JS,可以视作JS的超集</li>
</ul>
<blockquote>
<p>所有的JS语言，同时也是TS语言，而TS比今天的JS，更像未来的JS</p>
</blockquote>
<ul>
<li><a href="https://blog.csdn.net/zq9955/article/details/107863468">最全的区别</a></li>
</ul>
<h2 id="什么是net">什么是.Net</h2>
<ul>
<li>.Net(读作 dotnet)一般指的是 .Net平台 和 .Net Framework框架</li>
</ul>
<blockquote>
<p><strong>平台</strong>可以理解为一个厨房, 其中做菜用的&quot;柴米油盐酱醋茶&quot;就是<strong>框架</strong></p>
</blockquote>
<ul>
<li>因此: 框架<strong>包含于</strong>平台</li>
</ul>
<blockquote>
<p><strong>平台</strong>好比是&quot;中国移动互联网平台&quot;, 是实现功能的<strong>基础</strong><br>
而世界各地还有许许多多&quot;信号塔&quot;, 他们保证了平台的正常运转, 他们就是<strong>框架</strong></p>
</blockquote>
<hr>
<h1 id="总结-框架是平台不可或缺的一部分-为平台开发出来的应用的稳定运转提供保障"><strong>总结:</strong> <strong>框架</strong>是<strong>平台</strong>不可或缺的一部分, 为平台开发出来的应用的稳定运转提供保障</h1>
]]></content>
		</item>
		
		<item>
			<title></title>
			<link>https://zhydada.github.io/posts/js%E7%AC%94%E8%AE%B0___2022-07-23_11-20/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/js%E7%AC%94%E8%AE%B0___2022-07-23_11-20/</guid>
			<description>目录 数组 基本函数 高阶函数 循环 字符串 Audio AudioContext 声明 方法 AnalyserNode 声明 方法 AudioBuffer 和 buffer 声明 例子 异步处理 promise 构造promise resolve和reject then和ca</description>
			<content type="html"><![CDATA[<p>目录</p>
<ul>
<li><a href="#%E6%95%B0%E7%BB%84">数组</a>
<ul>
<li><a href="#%E5%9F%BA%E6%9C%AC%E5%87%BD%E6%95%B0">基本函数</a></li>
<li><a href="#%E9%AB%98%E9%98%B6%E5%87%BD%E6%95%B0">高阶函数</a></li>
<li><a href="#%E5%BE%AA%E7%8E%AF">循环</a></li>
</ul>
</li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%B2">字符串</a></li>
<li><a href="#audio">Audio</a>
<ul>
<li><a href="#audiocontext">AudioContext</a>
<ul>
<li><a href="#%E5%A3%B0%E6%98%8E">声明</a></li>
<li><a href="#%E6%96%B9%E6%B3%95">方法</a></li>
</ul>
</li>
<li><a href="#analysernode">AnalyserNode</a>
<ul>
<li><a href="#%E5%A3%B0%E6%98%8E-1">声明</a></li>
<li><a href="#%E6%96%B9%E6%B3%95-1">方法</a></li>
</ul>
</li>
<li><a href="#audiobuffer-%E5%92%8C-buffer">AudioBuffer 和 buffer</a>
<ul>
<li><a href="#%E5%A3%B0%E6%98%8E-2">声明</a></li>
<li><a href="#%E4%BE%8B%E5%AD%90">例子</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%BC%82%E6%AD%A5%E5%A4%84%E7%90%86">异步处理</a>
<ul>
<li><a href="#promise">promise</a>
<ul>
<li><a href="#%E6%9E%84%E9%80%A0promise">构造promise</a></li>
<li><a href="#resolve%E5%92%8Creject">resolve和reject</a></li>
<li><a href="#then%E5%92%8Ccatch">then和catch</a></li>
</ul>
</li>
<li><a href="#js%E5%BC%95%E6%93%8E%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F">JS引擎的执行顺序</a>
<ul>
<li><a href="#%E5%90%8C%E6%AD%A5%E4%BB%BB%E5%8A%A1%E5%92%8C%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1">同步任务和异步任务</a></li>
<li><a href="#%E5%AE%8F%E4%BB%BB%E5%8A%A1%E5%92%8C%E5%BE%AE%E4%BB%BB%E5%8A%A1">宏任务和微任务</a></li>
<li><a href="#%E6%80%BB%E7%BB%93">总结</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%AE%9E%E5%B8%B8%E6%9C%89-%E7%94%A8%E7%9A%84%E5%87%BD%E6%95%B0">实/常/有 用的函数</a>
<ul>
<li><a href="#%E6%97%B6%E9%97%B4%E6%88%B3">时间戳</a></li>
<li><a href="#json">JSON</a></li>
<li><a href="#cookie">cookie</a></li>
<li><a href="#%E6%9D%82">杂</a></li>
</ul>
</li>
<li><a href="#%E5%8F%82%E8%80%83%E6%9D%A5%E6%BA%90">参考来源</a></li>
</ul>
<h1 id="数组">数组</h1>
<h2 id="基本函数">基本函数</h2>
<blockquote>
<p>array.push()</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 在数组的末尾添加一个元素</li>
<li><strong>返回:</strong> 新数组的<strong>长度</strong></li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.push(true);
&lt; 7
&gt; array
&lt; [1, 9, 2, 4, &#39;a&#39;, 10, true]
</code></pre><blockquote>
<p>array.pop()</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 删除最后一个元素</li>
<li><strong>返回:</strong> ta的值</li>
<li><strong>注意:</strong> 不要求参数(输了也没用)</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.pop();
&lt; 10
&gt; array
&lt; [1, 9, 2, 4, &#39;a&#39;]
</code></pre><blockquote>
<p>array.shift();</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 弹出数组的第一个元素</li>
<li><strong>返回:</strong> 第一个元素</li>
<li><strong>备注:</strong> 会改变原先的数组</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.shift();
&lt; 1
&gt; array
&lt; [9, 2, 4, &#39;a&#39;, 10]
</code></pre><blockquote>
<p>array.unshift(val);</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 在第一个元素前插入被传入的值</li>
<li><strong>返回:</strong> 新数组的长度</li>
<li><strong>备注:</strong> 原先的每个元素的序号+1</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.unshift(&#34;zhy&#34;);
&lt; 7
&gt; array
&lt; [&#39;zhy&#39;, 1, 9, 2, 4, &#39;a&#39;, 10]
</code></pre><blockquote>
<p>array.splice(n1,n2)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 从数组中按序号<strong>剪切</strong>出一段新数组, 同时也会改变原数组</li>
<li><strong>返回:</strong> 剪切出来的新数组</li>
<li><strong>参数:</strong> 参数n1是指从array[n1]这一元素开始, n2是指新数组的<strong>长度</strong></li>
<li><strong>注意:</strong> n2即便很大也不会使新数组的长度变得很大, 只会一直剪切到原数组的最后一个元素为止</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.splice(1,3)
&lt; [9, 2, 4]
&gt; array
&lt; [1, &#39;a&#39;, 10]
&gt; array.splice(1,9)
&lt; [&#39;a&#39;, 10]
&gt; array
&lt; [1]
</code></pre><blockquote>
<p>array.slice(n1,n2);</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 从数组中按序号<strong>复制</strong>出一个新数组</li>
<li><strong>返回:</strong> 新数组</li>
<li><strong>参数:</strong> n1是指开始的序号, array[n1]这个元素<strong>不取</strong>; n2是指结束的序号, array[n2]这个元素<strong>取</strong></li>
<li><strong>注意:</strong> 1. 是复制, 原数组无变化, 要与splice区分<br>
1. 遵循<strong>左开右闭</strong>的原则</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10]
&gt; array.slice(3,5)
&lt; [4, &#39;a&#39;]
&gt; array
&lt; [1, 9, 2, 4, &#39;a&#39;, 10]
</code></pre><blockquote>
<p>array.join(str)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将数组的每个元素之间用str连接起来</li>
<li><strong>返回:</strong> 一个字符串</li>
<li><strong>参数:</strong> 一个可以被转为string的东西(数字,string之类)</li>
<li><strong>备注:</strong> 原数组不变化</li>
</ul>
<pre tabindex="0"><code>&gt; var array = [1,9,2,4,&#34;a&#34;,10];
&gt; array.join(&#34;|&#34;)
&lt; &#39;1|9|2|4|a|10&#39;
</code></pre><blockquote>
<p>arry = array1.concat(array2, array3)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将多个数组连接起来</li>
<li><strong>返回:</strong> 组合而成的新数组</li>
<li><strong>参数:</strong> 多个数组对象(按顺序)</li>
<li><strong>注意:</strong> 原数组不变化, 一定要获取返回值</li>
</ul>
<pre tabindex="0"><code>&gt; var array1 = [1,2,3];
&gt; var array2 = [4,5,6];
&gt; var array3 = [7,8,9];
&gt; var arrayA = array1.concat(array2,array3);
&gt; arrayA
&lt;  [1, 2, 3, 4, 5, 6, 7, 8, 9]
&gt; array3.concat(array1,array2);
&lt;  [7, 8, 9, 1, 2, 3, 4, 5, 6]
</code></pre><h2 id="高阶函数">高阶函数</h2>
<blockquote>
<p>array.map(function)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将一个函数作用在数组的每个元素上, 并用其返回值组成新的数组后输出</li>
<li><strong>返回:</strong> 加工后产生的新数组</li>
<li><strong>参数:</strong> 仅回调函数自身, 而回调函数会接收3个参数: <code>callback(currentValue, index, array)</code></li>
<li><strong>注意:</strong> 原数组不发生改变</li>
</ul>
<pre tabindex="0"><code>&gt; var aaa = [1, 3, 5];
&gt; function double(x) {
      return x * 2;
  } 
&gt; aaa.map(double);
&lt; [2, 6, 10]
&gt; aaa;
&lt; [1, 3, 5]
</code></pre><blockquote>
<p>array.reduce(function)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 函数要求两个变量, 函数先作用于前两个元素, 并把返回值和数组的下一个元素再次作为参数继续运算</li>
<li><strong>返回:</strong> 最终的一个结果, 视function的返回值而定</li>
<li><strong>参数:</strong> function要求两个参数</li>
<li><strong>备注:</strong> 其效果展开来看如下: <code>[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)</code></li>
</ul>
<pre tabindex="0"><code>&gt; var arr = [1, 3, 5, 7, 9];
&gt; arr.reduce(function (x, y) {
      return x + y;
  }); 
&lt; 25
</code></pre><blockquote>
<p>array.filter(function(element, index, self){})</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 把<code>Array</code>的某些元素过滤掉，然后返回剩下的元素组成的集合</li>
<li><strong>返回:</strong> 一个筛选后的数组</li>
<li><strong>参数:</strong> 一个回调函数, 应当返回一个<em>布尔值</em>, 其参数有三个:
<ul>
<li><code>element</code>: 表示元素</li>
<li><code>index</code>: 元素位置</li>
<li><code>self</code>: 数组本身</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>&gt; var arr = [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;];
&gt; var r = arr.filter(function (element, index, self) {
      console.log(element); // 依次打印&#39;A&#39;, &#39;B&#39;, &#39;C&#39;
      console.log(index); // 依次打印0, 1, 2
      console.log(self); // self就是变量arr
      return true;
  });
&lt; &#39;A&#39;
&lt; 0
&lt; arr
&lt; &#39;B&#39;
&lt; 1
&lt; arr
&lt; &#39;C&#39;
&lt; 2
&lt; arr
</code></pre><h2 id="循环">循环</h2>
<blockquote>
<p>for(a in aaa)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 循环得到一个对象的所有属性的简洁写法</li>
<li><strong>参数:</strong> 这里的<code>a</code>是<code>key</code>或者说是<code>property</code></li>
<li><strong>注意:</strong> 这里得到的<code>a</code>是<code>string</code>的形式, 千万别写<code>aaa.a</code>!!!</li>
<li><strong>备注:</strong> 最好是对一个<code>object</code>使用</li>
</ul>
<pre tabindex="0"><code>&gt; let aaa = {
  &#34;name&#34;: &#34;zhyDaDa&#34;,
  &#34;hobby&#34;: &#34;programming&#34;,
  &#34;age&#34;: 3
  }
&gt; for(a in aaa){
    console.log(a);
    console.log(aaa[a]);
  }
&lt; name
&lt; zhyDaDa
&lt; hobby
&lt; programming
&lt; age
&lt; 3
</code></pre><blockquote>
<p>for(let b of bbb)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 循环得到数组中每一个值的简洁写法</li>
<li><strong>参数:</strong> <code>b</code>是一个<em>value</em>而非<em>index</em></li>
<li><strong>备注:</strong> 最好是对一个<code>array</code>使用</li>
</ul>
<pre tabindex="0"><code>&gt; var bbb = [1,&#39;b&#39;,2,4,&#34;zhyDaDa&#34;,10];
&gt; for(let b of bbb){
    console.log(b);
  }
&lt; 1
&lt; b
&lt; 2
&lt; 4
&lt; zhyDaDa
&lt; 10
</code></pre><h1 id="字符串">字符串</h1>
<blockquote>
<p>parseInt(string, radix)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 可解析一个字符串，并返回一个整数</li>
<li><strong>返回:</strong> 整数</li>
<li><strong>参数:</strong> +
<ul>
<li><code>string</code>: 要被解析的字符串。</li>
<li><code>radix</code>: 可选, 表示要解析的数字的基数; 该值介于 2 ~ 36 之间</li>
</ul>
</li>
<li><strong>备注:</strong>
<ul>
<li>如果 string 以 &ldquo;0x&rdquo; 开头，parseInt() 会把 string 的其余部分解析为十六进制的整数。</li>
<li>如果 string 以 0 开头，那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。</li>
<li>如果 string 以 1 ~ 9 的数字开头，parseInt() 将把它解析为十进制的整数。</li>
</ul>
</li>
</ul>
<pre tabindex="0"><code>&gt; parseInt(&#34;10.33&#34;)
&lt; 10
&gt; parseInt(&#34;10&#34;,8)
&lt; 8
&gt; parseInt(&#34;0x10&#34;)
&lt; 16
</code></pre><blockquote>
<p>Number(object)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 把不同的对象转换为数字</li>
<li><strong>返回:</strong> 数字以及<code>NaN</code></li>
<li><strong>参数:</strong> 一个JS对象</li>
<li><strong>备注:</strong> 如果没有提供参数, 则返回0</li>
</ul>
<pre tabindex="0"><code>&gt; Number(true)
&lt; 1
&gt; Number(false)
&lt; 0
&gt; Number(&#34;432&#34;)
&lt; 432
&gt; Number(&#34;4 3 2&#34;)
&lt; NaN
</code></pre><h1 id="audio">Audio</h1>
<p>所有工作都在<strong>AudioContext</strong>中实现<br>
这个对象包含有很多个节点(nodes), 各司其职<br>
一般的工作流程如下:</p>
<ol>
<li>创建一个<strong>AudioContext</strong></li>
<li>在AudioContext中，创建<strong>声源节点</strong>——例如<code>&lt;audio&gt;</code>标签，振动发声器 (oscillator)，音频流(stream)</li>
<li>创建<strong>特效节点</strong>——例如混响，双二阶滤波，声相控制，音频振幅压缩</li>
<li>选择音频的<strong>终点</strong>——例如系统的扬声器</li>
<li><strong>连接</strong>声源和特效，以及特效和终点。</li>
</ol>
<blockquote>
<p><code>AudioContext</code></p>
<blockquote>
<p><code>Inputs</code> =&gt; <code>Effects</code> =&gt; <code>Destination</code></p>
</blockquote>
</blockquote>
<h2 id="audiocontext">AudioContext</h2>
<h3 id="声明">声明</h3>
<blockquote>
<p>var audioCtx = new AudioContext;</p>
</blockquote>
<p>跨浏览器的通用方法:</p>
<pre tabindex="0"><code>var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();
</code></pre><h3 id="方法">方法</h3>
<blockquote>
<p>audioCtx.close();</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 释放占用的系统资源, 停止处理音频</li>
<li><strong>返回:</strong> promise</li>
<li><strong>备注:</strong> 可以接then处理后续动作</li>
</ul>
<pre tabindex="0"><code>audioCtx.close().then(function() { ... });
</code></pre><blockquote>
<p>audioCtx.suspend();
audioCtx.resume();</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 暂停和继续</li>
<li><strong>返回:</strong> promise</li>
<li><strong>备注:</strong> 如果返回失败, 就说明audioCtx已经被关闭</li>
</ul>
<h2 id="analysernode">AnalyserNode</h2>
<h3 id="声明-1">声明</h3>
<blockquote>
<p>var analyser = audioCtx.createAnalyser();</p>
</blockquote>
<h3 id="方法-1">方法</h3>
<blockquote>
<p>analyser.getFloatFrequencyData(array);
analyser.getByteFrequencyData(array);</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 获取频率数据, 并以数组形式储存, 前者是32位浮点, 后者是Uint8Array（无符号字节数组）</li>
<li><strong>返回:</strong> 数组</li>
<li><strong>备注:</strong> 此数组表示的频率范围为 0 ~ 22050 Hz，每个元素表示对应频率上的信号分量强度，单位为分贝</li>
</ul>
<h2 id="audiobuffer-和-buffer">AudioBuffer 和 buffer</h2>
<p>缓存区（buffer）包含以下数据：不间断的 IEEE754 32 位线性 PCM，<strong>从 -1 到 1 的范围额定</strong>，就是说，32 位的浮点缓存区的每个样本在 -1.0 到 1.0 之间。</p>
<h3 id="声明-2">声明</h3>
<blockquote>
<p>var audioBuffer = new AudioBuffer(context[, options]);</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 创建一个新的 AudioBuffer 对象</li>
<li><strong>返回:</strong> 一个新的 AudioBuffer 对象实例</li>
<li><strong>参数:</strong>
<ul>
<li>context: audioCtx</li>
<li>option可选参数
<ul>
<li>length: buffer 中采样帧的长度。</li>
<li>numberOfChannels: buffer 的通道数。默认值为 1.</li>
<li>sampleRate: buffer 的采样率 (Hz). 默认值为构造此对象时使用的 context 的采样率。</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>AudioContext.createBuffer(Number numOfChannels, Number length, Number sampleRate);</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 建一个空白的 AudioBuffer 对象</li>
<li><strong>返回:</strong> 一个 AudioBuffer</li>
<li><strong>参数:</strong>
<ul>
<li>
<p>numOfChannels 
一个定义了 buffer 中包含的声频通道数量的整数。 一个标准的实现必须包含至少 32 个声频通道。</p>
</li>
<li>
<p>length<br>
一个代表 buffer 中的样本帧数的整数。</p>
</li>
<li>
<p>sampleRate<br>
线性音频样本的采样率，即每一秒包含的关键帧的个数。实现过程中必须支持 22050 ～ 96000 的采样率。</p>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>var source = audioCtx.createBufferSource()</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 建立一个一个 AudioBufferSourceNode 节点</li>
<li><strong>参数:</strong> 参数的说明</li>
<li><strong>注意:</strong><br>
一个 AudioBufferSourceNode <strong>只能被播放一次</strong>，也就是说，每次调用 start() (en-US) 之后，如果还想再播放一遍同样的声音，那么就需要再创建一个 AudioBufferSourceNode。</li>
</ul>
<h3 id="例子">例子</h3>
<pre tabindex="0"><code>// 创建一个双声道的缓冲
var myArrayBuffer = audioCtx.createBuffer(2, frameCount, audioCtx.sampleRate)
// 提取其中一个声道的缓冲, 可以以数组的方式修改它
var nowBuffering = myArrayBuffer.getChannelData(0);
for (var i = 0; i &lt; frameCount; i++) {
  // audio needs to be in [-1.0; 1.0]
  nowBuffering[i] = Math.random() * 2 - 1;
}

// 要想播放缓冲, 就要有一个资源节点
var source = audioCtx.createBufferSource();
// 把刚才处理好的缓冲交过去
source.buffer = myArrayBuffer;

// 最后把这个资源绑定到最终的节点上去
source.connect(audioCtx.destination);
// 在最终的节点上实现播放动作 
source.start();
</code></pre><h1 id="异步处理">异步处理</h1>
<h2 id="promise">promise</h2>
<p><em><strong>promise</strong></em>是一个 <strong>构造函数</strong>, 传入一个要运行的函数<code>M</code>作为参数, 返回一个 <em><strong>promise</strong></em> <strong>实例</strong><br>
在M运行过程中, 会调用两个函数(<code>resolve</code>和<code>reject</code>)表示完成与否<br>
紧接着<em><strong>promise</strong></em>实例后有<code>then</code>和<code>catch</code>这两个回调函数, 他们会根据<em><strong>promise</strong></em>的返回传递参数, 调用相应函数</p>
<p><em><strong>promise</strong></em>有三种状态:</p>
<ol>
<li><strong>Fulfilled</strong>: has-resolved, 表示成功解决，这时会调用 onFulfilled.</li>
<li><strong>Rejected</strong>: has-rejected, 表示解决失败，此时会调用 onRejected.</li>
<li><strong>Pending</strong>: unresolve, 表示待解决，既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态.</li>
</ol>
<blockquote>
<p><code>resolve</code>和<code>reject</code> 用来切换状态<br>
<code>then</code>和<code>catch</code> 用来感知状态</p>
</blockquote>
<h3 id="构造promise">构造promise</h3>
<pre tabindex="0"><code>let M = new Promise((resolve, reject) =&gt; {
    if(done)
        resolve(data.done); //处理成功
    if(!done)
        reject(data.fail); //处理成功
});
</code></pre><p>这里<em><strong>Promise</strong></em>构造器接受一个函数(一般是 <em>无名函数</em> ), 这个函数有<strong>两个参数</strong><br>
参数是两个<strong>函数名</strong>, 一般是<code>resolve</code>和<code>reject</code><br>
无名函数的内部就是要运行的函数了<br>
<em><strong>promise</strong></em> <strong>实例</strong>构造完成就开始运行<br>
下一轮<strong>Event Loop</strong>就无效了</p>
<blockquote>
<p>原因很简单: 状态显示的不是 <strong>Pending</strong>, 说明已经完成了</p>
</blockquote>
<h3 id="resolve和reject">resolve和reject</h3>
<p>当调用<code>resolve</code>时, 其参数是要传出去的数据, 其效果是把所在的这个 <em><strong>promise</strong></em> <strong>实例</strong> 的状态改成 <strong>fulfilled</strong><br>
当调用<code>reject</code>时, 其参数是错误信息, 其效果是把所在的这个 <em><strong>promise</strong></em> <strong>实例</strong> 的状态改成 <strong>rejected</strong></p>
<p><strong>注意</strong>:</p>
<ul>
<li>这两个函数<strong>不能</strong>类比 <em><strong>return</strong></em>! 函数还会继续走完</li>
<li>这两个函数只干两件事:
<ol>
<li>修改状态</li>
<li>传递数据</li>
</ol>
</li>
<li>修改状态只能改未完成的状态, 也就是说, <code>resolve</code>和<code>reject</code> <strong>哪个在前面哪个生效</strong></li>
</ul>
<h3 id="then和catch">then和catch</h3>
<p>他们能感知他们对应的 <em><strong>promise</strong></em> <strong>实例</strong> 的状态<br>
他们的参数是回调函数的函数名<br>
<code>M.then(f)</code>或是<code>M.catch(f)</code><br>
当M转变成<strong>Fulfilled</strong>状态时,<em><strong>then</strong></em>就被送入 <em>&ldquo;微任务&rdquo;</em><br>
当 &ldquo;<em>宏任务</em>&rdquo; 完成后, <em><strong>then</strong></em>将<code>M</code>的<code>resolve</code>传递出的数据作为参数传递给回调函数<br>
<em><strong>catch</strong></em>同理</p>
<p><strong>注意</strong>: <code>then</code>和<code>catch</code>本身也是 <em><strong>promise</strong></em> <strong>实例</strong></p>
<h2 id="js引擎的执行顺序">JS引擎的执行顺序</h2>
<p>明确: <strong>JS 执行机制是单线程</strong></p>
<h3 id="同步任务和异步任务">同步任务和异步任务</h3>
<p>JS有一个<strong>Event Loop</strong>的概念, 可以理解为<em>手头正要做的事</em><br>
JS的主线程就会按着上面登记的任务一个个完成<br>
如果任务出了问题, JS就报错, 停止, 产生<strong>卡死现象</strong><br>
任务有一个简单的分类:</p>
<ul>
<li>同步任务</li>
<li>异步任务</li>
</ul>
<p>同步进入<strong>主线程</strong>，异步进入<strong>Event Table</strong><br>
这个<strong>Event Table</strong>可以理解为<em>任务规划表</em><br>
上面登记的内容是一些函数和ta对应的出场条件<br>
当满足条件时, 这个函数会作为一项任务推入 <strong>Event Queue</strong><br>
<strong>Event Queue</strong>可以理解为<em>待办清单</em><br>
主进程空闲后, 就把<strong>Event Queue</strong>全部放到主进程中</p>
<blockquote>
<p>打个比喻(纯粹是假想的, 只是用于理解记忆):<br>
<strong>主进程</strong>: <code>[&quot;做作业()&quot;, &quot;准备开始吃中饭()&quot;]</code><br>
<strong>Event Table</strong>: <code>[[&quot;4点&quot;, &quot;买菜()&quot;], [&quot;5点&quot;, &quot;烧菜()&quot;], [&quot;6点&quot;, &quot;吃晚饭()&quot;]]</code><br>
<strong>Event Queue</strong>: <code>[[&quot;吃饭前&quot;, &quot;打开手机()&quot;], [&quot;吃饭时&quot;, &quot;看下饭视频()&quot;]]</code></p>
</blockquote>
<h3 id="宏任务和微任务">宏任务和微任务</h3>
<p><strong>主进程</strong>更细分来看, 其实还能划分成<strong>宏任务</strong>和<strong>微任务</strong></p>
<ul>
<li><strong>macro-task</strong>(<strong>宏任务</strong>)：包括整体代码script，setTimeout，setInterval</li>
<li><strong>micro-task</strong>(<strong>微任务</strong>)：Promise，process.nextTic</li>
</ul>
<h3 id="总结">总结</h3>
<p>按顺序排下来</p>
<ol>
<li>主进程</li>
<li>宏任务</li>
<li>微任务</li>
<li>装载<strong>Event Queue</strong>到主进程</li>
<li>回到第2步</li>
</ol>
<h1 id="实常有-用的函数">实/常/有 用的函数</h1>
<h2 id="时间戳">时间戳</h2>
<blockquote>
<p>Date.now()<br>
new Date().getTime()<br>
(new Date()).valueOf()<br>
Number(new Date())</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 获得当前的时间戳</li>
<li><strong>返回:</strong> 时间戳(数字形式)</li>
</ul>
<pre tabindex="0"><code>&gt; Date.now()
&lt; 1666958673590
&gt; new Date().getTime()
&lt; 1666958656425
</code></pre><blockquote>
<p>new Date(time)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将时间戳转化为字符串形式</li>
<li><strong>返回:</strong> 标准格式的字符串形式的时间表示</li>
<li><strong>参数:</strong> <code>time</code>是数字形式的<strong>时间戳</strong></li>
<li><strong>注意:</strong> 这里的字符串会按照现在的环境变化, 下面给出两个版本</li>
</ul>
<pre tabindex="0"><code>&gt; new Date(1666958673590)
&lt; Fri Oct 28 2022 20:04:33 GMT+0800 (中国标准时间)
&gt; new Date(1645099205343)  
&lt; Thu Feb 17 2022 20:00:05 GMT+0800 (CST)
</code></pre><blockquote>
<p>生成 &lsquo;yyyy/MM/dd 上(下)午 hh:mm:ss&rsquo; 格式</p>
</blockquote>
<pre tabindex="0"><code>function getLocalTime(n){
	return new Date(parseInt(n)).toLocaleString().replace(/:\d{1,2}$/,&#39;&#39;);
}
getLocalTime(1645099205343) //&#34;2022/2/17 下午8:00&#34;
</code></pre><blockquote>
<p>当前系统区域设置格式(toLocaleDateString和toLocaleTimeString)</p>
</blockquote>
<pre tabindex="0"><code>(new Date()).toLocaleDateString() + &#34; &#34; + (new Date()).toLocaleTimeString() 
//&#39;2022/2/18 下午6:51:09&#39;
</code></pre><blockquote>
<p>格林威治标准时间(toGMTString)</p>
</blockquote>
<pre tabindex="0"><code>(new Date()).toGMTString() 
//&#34;Fri, 18 Feb 2022 10:53:01 GMT&#34;
</code></pre><h2 id="json">JSON</h2>
<blockquote>
<p>JSON.parse(&ldquo;json_string&rdquo;)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将一个JSON字符串解析成JavaScript对象</li>
<li><strong>返回:</strong> 一个对象, 可以直接用</li>
<li><strong>参数:</strong> json字符串</li>
<li><strong>备注:</strong> 前后端交互</li>
</ul>
<pre tabindex="0"><code>&gt; var json_info = &#39;{&#34;a&#34;:1,&#34;b&#34;:&#34;zhyDaDa&#34;,&#34;c&#34;:null}&#39;
&gt; var js_obj = JSON.parse(json_info)
&gt; js_obj
&lt; {a: 1, b: &#39;zhyDaDa&#39;, c: null}
</code></pre><blockquote>
<p>JSON.stringify(value, replacer, space)</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 将JavaScript值转换成JSON对象</li>
<li><strong>返回:</strong> 字符串, json的格式</li>
<li><strong>参数:</strong>
<ul>
<li><strong>value</strong>: 一个对象, 可以是数组</li>
<li><strong>replacer</strong>: 将对象的值传入, 得到的返回值写入json</li>
<li><strong>space</strong>: 用几个空格缩进</li>
</ul>
</li>
<li><strong>备注:</strong> 前后端交互</li>
</ul>
<pre tabindex="0"><code>&gt; var js_obj = {a: 1, b: &#39;zhyDaDa&#39;, &#34;c&#34;: null}
&gt; var json_string = JSON.stringify(js_obj)
&gt; json_string
&lt; &#39;{&#34;a&#34;:1,&#34;b&#34;:&#34;zhyDaDa&#34;,&#34;c&#34;:null}&#39;
</code></pre><h2 id="cookie">cookie</h2>
<blockquote>
<p>设置cookie</p>
</blockquote>
<ul>
<li><strong>参数:</strong> iDay是有效天数</li>
</ul>
<pre tabindex="0"><code>function setCookie(name,value,iDay){
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + iDay);
    document.cookie = name + &#34;=&#34; + value + &#34;;expires=&#34; + oDate;
}
</code></pre><blockquote>
<p>读取cookie</p>
</blockquote>
<ul>
<li><strong>注意:</strong> 该方法简单地认为cookie中只有一个“=”，即key=value，如有更多需求可以在此基础上完善:</li>
</ul>
<pre tabindex="0"><code>function getCookie(name){
    //例如cookie是&#34;username=abc; password=123&#34;
    var arr = document.cookie.split(&#39;; &#39;);//用“;”和空格来划分cookie
    for(var i = 0 ;i &lt; arr.length ; i++){
        var arr2 = arr[i].split(&#34;=&#34;);
        if(arr2[0] == name){
            return arr2[1];
        }
    }
    return &#34;&#34;;//整个遍历完没找到，就返回空值
}
</code></pre><blockquote>
<p>删除cookie</p>
</blockquote>
<ul>
<li><strong>备注:</strong> 原理就是覆盖, 然后时间设置成昨天</li>
</ul>
<pre tabindex="0"><code>function removeCookie(name){
    setCookie(name, &#34;1&#34;, -1)//第二个value值随便设个值，第三个值设为-1表示：昨天就过期了，赶紧删除
}
</code></pre><h2 id="杂">杂</h2>
<blockquote>
<p>完全深度复制</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 完全的复制一个数组或者对象, 并且两者独立互不影响</li>
<li><strong>返回:</strong> 克隆品</li>
<li><strong>参数:</strong> 要复制的对象, 以及是否是数组</li>
<li><strong>备注:</strong> 完美解决存储位置公用的问题</li>
</ul>
<pre tabindex="0"><code>var deepCopy = function (source,isArray) {
    var result = {};            
    if(isArray) var result = [];            
    for(var key in source) {                
        if(Object.prototype.toString.call(source[key])  === &#39;[object Object]&#39;) {
            result[key] = deepCopy(source[key])
        } if(Object.prototype.toString.call(source[key]) === &#39;[object Array]&#39;) {
            result[key] = deepCopy(source[key],1)
        } else {
            result[key] = source[key]
        }
    }            
    return result;
}
</code></pre><blockquote>
<p>获取最底层的document文档对象</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 该函数会返回 document 为最底层的 iframe 父页面的文档对象，从而避免了在多层嵌套 iframe 中访问元素时出现的问题</li>
<li><strong>备注:</strong> 并不改变现在的document, 因为document是只读的</li>
</ul>
<pre tabindex="0"><code>/**
 * 获取最顶层的文档对象。
 *
 * @returns {Document} 最顶层的文档对象。
 */
function getBaseDocument() {
    var currentWindow = window;

    while (currentWindow !== currentWindow.parent) {
        currentWindow = currentWindow.parent;
    }

    return currentWindow.document;
}
</code></pre><blockquote>
<p>直接无提示关闭页面</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 同上, 用js实现</li>
<li><strong>备注:</strong> 无提示</li>
</ul>
<pre tabindex="0"><code>let a = document.createElement(&#34;a&#34;);
a.href = &#34;javascript:window.opener=null;window.open(&#39;&#39;,&#39;_self&#39;);window.close();&#34;;
a.click();
</code></pre><blockquote>
<p>刷新页面</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 如题</li>
</ul>
<pre tabindex="0"><code>location.reload();
</code></pre><blockquote>
<p>消除所有定时器</p>
</blockquote>
<ul>
<li><strong>作用:</strong> 如题</li>
</ul>
<pre tabindex="0"><code>let end = setInterval(function () { }, 10000);
for (let i = 1; i &lt;= end; i++) {
    clearInterval(i);
}
</code></pre><blockquote>
<p>地毯式搜索所有子iframe中的所有元素</p>
</blockquote>
<ul>
<li><strong>注意:</strong> 按需要改变选择器的规则</li>
</ul>
<pre tabindex="0"><code>function searchIframes(doc, pattern) {
    let elementList=[];
    doc.querySelectorAll(&#39;iframe&#39;).forEach(iframe =&gt; {
        try {
            iframeDoc = iframe.contentDocument || iframe.contentWindow.document
            elementList = elementList.concat(iframeDoc.querySelectorAll(pattern) || [])
            elementList = elementList.concat(searchIframes(iframeDoc) || [])
        } catch (e) { // 直接忽略错误的 iframe (e.g. cross-origin)
        }
    })
    return elementList;
}
</code></pre><blockquote>
<p>获取指定名称的 cookie 值</p>
</blockquote>
<pre tabindex="0"><code>getCookie = name =&gt; `; ${document.cookie}`.split(`; ${name}=`).pop().split(&#39;;&#39;).shift()
</code></pre><blockquote>
<p>获取URL中指定名称的值</p>
</blockquote>
<ul>
<li><strong>备注:</strong> 没有找到就返回false</li>
</ul>
<pre tabindex="0"><code>getQueryVariable = (variable) =&gt; {
    let q = window.location.search.substring(1),
        v = q.split(&#34;&amp;&#34;),
        r = false;
    for (let i = 0, l = v.length; i &lt; l; i++) {
        let p = v[i].split(&#34;=&#34;);
        p[0] == variable &amp;&amp; (r = p[1]);
    }
    return r;
}
</code></pre><blockquote>
<p>睡眠函数</p>
</blockquote>
<pre tabindex="0"><code>function sleep(interval) {
    return new Promise((success, fail) =&gt; {
        setTimeout(success, interval);
    });
}
</code></pre><blockquote>
<p>简易的md转html</p>
</blockquote>
<ul>
<li><strong>备注:</strong> 因为多行文字要用模板字符串, 所以代码块的标识符用了<code>$</code>, 切记切记</li>
</ul>
<pre tabindex="0"><code>var md2html = function(md) {
    // 分别替换两个尖括号
    md = md.replace(/&lt;/gm, &#34;&amp;lt;&#34;);
    md = md.replace(/&gt;/gm, &#34;&amp;gt;&#34;);

    // 加粗
    md = md.replace(/\*\*(.+?)\*\*/gm, &#34;&lt;strong&gt;$1&lt;/strong&gt;&#34;);

    // 代码
    md = md.replace(/\$(.+?)\$/gm, &#34;&lt;code&gt;$1&lt;/code&gt;&#34;);

    // 链接
    md = md.replace(/\[(.+?)\]\((.+?)\)/gm, &#34;&lt;a target=&#39;_blank&#39; href=&#39;$2&#39;&gt;$1&lt;/a&gt;&#34;);

    // 句子中间的多个空格替换为html中相同数量的空格
    md = md.replace(/  /gm, &#34;&amp;nbsp;&amp;nbsp;&#34;);

    // 一级标题
    md = md.replace(/^# (.+?)$/gm, &#34;&lt;h1&gt;$1&lt;/h1&gt;&#34;);

    // 二级标题
    md = md.replace(/^## (.+?)$/gm, &#34;&lt;h2&gt;$1&lt;/h2&gt;&#34;);

    // 三级标题
    md = md.replace(/^### (.+?)$/gm, &#34;&lt;h3&gt;$1&lt;/h3&gt;&#34;);

    // 其余的行前后加上p标签, 如果一行的末尾有2个空格则在末尾加上&lt;br&gt;
    md = md.replace(/^(.+?)$/gm, &#34;&lt;p&gt;$1&lt;/p&gt;&#34;);
    md = md.replace(/&lt;p&gt;(.+?)  &lt;\/p&gt;/gm, &#34;&lt;p&gt;$1&lt;/p&gt;&lt;br&gt;&#34;);

    return md;

}
</code></pre><h1 id="参考来源">参考来源</h1>
<ol>
<li><a href="https://www.liaoxuefeng.com/">廖雪峰的官方网站</a></li>
<li><a href="https://www.runoob.com/js/js-tutorial.html">菜鸟教程</a></li>
<li><a href="https://blog.csdn.net/qq_44741441/article/details/122990466">在JavaScript中时间戳</a></li>
</ol>
]]></content>
		</item>
		
		<item>
			<title></title>
			<link>https://zhydada.github.io/posts/markdown_%E8%87%AA%E6%88%91%E5%B0%9D%E8%AF%95___2022-07-20_14-37/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/markdown_%E8%87%AA%E6%88%91%E5%B0%9D%E8%AF%95___2022-07-20_14-37/</guid>
			<description>$$ \overbrace{a+b+c+d}^{20}\ 3.23\dot9 $$ F11 $$ \lim_{x\to+2} \frac{\sqrt{x^2-4}}{2x\sqrt{x}} $$ 积分表 $\int kdx=kx+C$ $\int x^udx=\frac{x^{u+1}}{u+1}+C$ $\int \frac{1}{x}dx=ln|x|+C$ $\int \frac{1}{1+x^2}dx=\arctan x+C$ $$ $$ $$ $$ $$ $$ 删除线 下划线 $$ \theta \overline{\theta} \underline{\theta} $$</description>
			<content type="html"><![CDATA[<p>$$
\overbrace{a+b+c+d}^{20}\
3.23\dot9
$$</p>
<p><kbd>F11</kbd></p>
<p>$$</p>
<p>\lim_{x\to+2} \frac{\sqrt{x^2-4}}{2x\sqrt{x}}</p>
<p>$$</p>
<h1 id="积分表">积分表</h1>
<ol>
<li>$\int kdx=kx+C$</li>
<li>$\int x^udx=\frac{x^{u+1}}{u+1}+C$</li>
<li>$\int \frac{1}{x}dx=ln|x|+C$</li>
<li>$\int \frac{1}{1+x^2}dx=\arctan x+C$</li>
<li>$$</li>
<li>$$</li>
<li>$$</li>
<li>$$</li>
<li>$$
$$</li>
</ol>
<p><del>删除线</del><br>
<u>下划线</u><br>
$$
\theta  \overline{\theta} \underline{\theta}
$$</p>
]]></content>
		</item>
		
		<item>
			<title></title>
			<link>https://zhydada.github.io/posts/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%AD%A6%E4%B9%A0___2022-08-24_13-42/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%AD%A6%E4%B9%A0___2022-08-24_13-42/</guid>
			<description>常用速查 匹配中文字符 匹配网址 系统学习 1. 入门 2. 匹配单个字符 3. 匹配一组字符 5. &amp;ldquo;贪婪型&amp;quot;元字符和&amp;quot;懒惰型&amp;quot</description>
			<content type="html"><![CDATA[<ul>
<li><a href="#%E5%B8%B8%E7%94%A8%E9%80%9F%E6%9F%A5">常用速查</a>
<ul>
<li><a href="#%E5%8C%B9%E9%85%8D%E4%B8%AD%E6%96%87%E5%AD%97%E7%AC%A6">匹配中文字符</a></li>
<li><a href="#%E5%8C%B9%E9%85%8D%E7%BD%91%E5%9D%80">匹配网址</a></li>
</ul>
</li>
<li><a href="#%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0">系统学习</a>
<ul>
<li><a href="#1-%E5%85%A5%E9%97%A8">1. 入门</a></li>
<li><a href="#2-%E5%8C%B9%E9%85%8D%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6">2. 匹配单个字符</a></li>
<li><a href="#3-%E5%8C%B9%E9%85%8D%E4%B8%80%E7%BB%84%E5%AD%97%E7%AC%A6">3. 匹配一组字符</a></li>
<li><a href="#5-%E8%B4%AA%E5%A9%AA%E5%9E%8B%E5%85%83%E5%AD%97%E7%AC%A6%E5%92%8C%E6%87%92%E6%83%B0%E5%9E%8B%E5%85%83%E5%AD%97%E7%AC%A6">5. &ldquo;贪婪型&quot;元字符和&quot;懒惰型&quot;元字符</a></li>
</ul>
</li>
</ul>
<h1 id="常用速查">常用速查</h1>
<h2 id="匹配中文字符">匹配中文字符</h2>
<blockquote>
<p><code>[\u4E00-\u9FFF]</code></p>
</blockquote>
<h2 id="匹配网址">匹配网址</h2>
<blockquote>
<p><code>[http://|ftp://|https://|www]?[^\u4e00-\u9fa5\s]*?\.[com|net|cn|me|tw|fr][^\u4e00-\u9fa5\s]*</code></p>
</blockquote>
<hr>
<h1 id="系统学习">系统学习</h1>
<blockquote>
<p>学习用书: <em>正则表达式必知必会</em></p>
</blockquote>
<h2 id="1-入门">1. 入门</h2>
<ul>
<li>
<p><strong>名称</strong>: <code>Regular Expression</code>(abbr. <em><strong>regex</strong></em>)</p>
</li>
<li>
<p><strong>定义</strong>: <strong>正则表达式</strong>是一些用来匹配和处理文本的<em>字符串</em></p>
</li>
<li>
<p><strong>功能</strong>:</p>
<ul>
<li>搜索(匹配文本)</li>
<li>替换(匹配并替换文本)</li>
</ul>
</li>
<li>
<p><strong>注意</strong>: 不同语言or软件在使用正则时有微小出入</p>
</li>
</ul>
<h2 id="2-匹配单个字符">2. 匹配单个字符</h2>
<ul>
<li><strong>纯文本</strong>: 放上对应的纯文本就ok</li>
<li><strong>任意字符</strong>: 用元字符(<em><strong>Metacharacter</strong></em>) <code>.</code> 来表示任意字符</li>
</ul>
<blockquote>
<p>这相当于<strong>Dos</strong>中的 <code>?</code> 以及<strong>SQL</strong>中的 <code>_</code></p>
</blockquote>
<ul>
<li><strong>转义符</strong>: <code>\</code> 是一个元字符, 其作用不言而喻, 就是将ta后面的有<em>特殊意义</em>的字符转换为纯文本</li>
</ul>
<blockquote>
<p>一般, 称一个实际的正则表达式为 <strong>模式</strong></p>
</blockquote>
<h2 id="3-匹配一组字符">3. 匹配一组字符</h2>
<ul>
<li><strong>字符集合区间</strong>: 在 <code>[]</code>中加入想要匹配的单个字符</li>
</ul>
<blockquote>
<p>例: <code>[Cp]a[Tt]</code>可以匹配到如下四个字符串</p>
<blockquote>
<p>pat paT Cat CaT</p>
</blockquote>
</blockquote>
<blockquote>
<p><strong>注意</strong>: 要想返回全部匹配结果就要用 <code>g</code> 标志(global)<br>
且不同语言or工具使用方法不同<br>
相似地, 如果要无视字母的大小写, 就要用 <code>i</code> 标志</p>
</blockquote>
<ul>
<li><strong>连字符</strong>: <code>-</code> 是元字符之一, ta的作用时表示ASCII字符表上, 其左右连接的字符间的所有字符</li>
</ul>
<blockquote>
<p><code>[0-9]</code>和<code>[0123456789]</code>完全等价</p>
</blockquote>
<ul>
<li>
<p><strong>常用的字符集和区间</strong>:</p>
<ul>
<li><code>[a-z]</code></li>
<li><code>[A-Z]</code></li>
<li><code>[0-9]</code></li>
</ul>
</li>
<li>
<p><strong>注意</strong>: <code>-</code> 的左右字符必须在ASCII上是前后关系, 否则无意义<br>
另外, <code>[A-z]</code> 会掺杂进Z和a之间的其他字符, 不推荐使用</p>
</li>
<li>
<p><strong>取非匹配</strong>: 元字符 <code>^</code> 如果出现在 <code>[]</code> 中间的最前面, 那么表示不匹配这个区间内的字符</p>
</li>
</ul>
<h2 id="5-贪婪型元字符和懒惰型元字符">5. &ldquo;贪婪型&quot;元字符和&quot;懒惰型&quot;元字符</h2>
<ul>
<li><strong>贪婪型</strong>: 在<em>一行内</em>尽可能<strong>多</strong>的匹配</li>
<li><strong>懒惰型</strong>: 在<em>一行内</em>尽可能<strong>少</strong>的匹配</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">贪婪型</th>
<th style="text-align:center">懒惰型</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">*</td>
<td style="text-align:center">*?</td>
</tr>
<tr>
<td style="text-align:center">+</td>
<td style="text-align:center">+?</td>
</tr>
<tr>
<td style="text-align:center">{n, }</td>
<td style="text-align:center">{n, }?</td>
</tr>
</tbody>
</table>
]]></content>
		</item>
		
		<item>
			<title></title>
			<link>https://zhydada.github.io/posts/%E7%94%A8%E6%9D%A5%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E7%94%A8%E6%9D%A5%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9/</guid>
			<description>注意正则表达式的使用! import re,os import datetime filePath = r&amp;quot;C:\Users\zhyDaDa\gpm\github.com\zhyDaDa\zhyDaDa.github.io\content\posts\test&amp;quot; fileList = os.listdir(filePath) temp_name = r&amp;quot;C:\Users\zhyDaDa\gpm\github.com\zhyDaDa\zhyDaDa.github.io\content\posts\test\temp.md&amp;quot; for md_file in fileList: fileName = filePath + &amp;ldquo;\&amp;rdquo; + md_file try: with open(fileName,&amp;lsquo;r&amp;rsquo;,encoding=&amp;lsquo;utf-8&amp;rsquo;) as f1,open(temp_name,&amp;lsquo;w&amp;rsquo;,encoding=&amp;lsquo;utf-8&amp;rsquo;) as f2: file_mtime = os.path.getmtime(fileName) #get timeinfo in float form file_mtime = datetime.datetime.fromtimestamp(file_mtime) #convert float time into date objective file_mtime = datetime.datetime.strftime(file_mtime, &amp;lsquo;%Y-%m-%d&amp;rsquo;) #convert date obj. to str in format</description>
			<content type="html"><![CDATA[<h1 id="注意正则表达式的使用">注意正则表达式的使用!</h1>
<p>import re,os
import datetime</p>
<p>filePath = r&quot;C:\Users\zhyDaDa\gpm\github.com\zhyDaDa\zhyDaDa.github.io\content\posts\test&quot;
fileList = os.listdir(filePath)
temp_name = r&quot;C:\Users\zhyDaDa\gpm\github.com\zhyDaDa\zhyDaDa.github.io\content\posts\test\temp.md&quot;
for md_file in fileList:
fileName = filePath + &ldquo;\&rdquo; + md_file
try:
with open(fileName,&lsquo;r&rsquo;,encoding=&lsquo;utf-8&rsquo;) as f1,open(temp_name,&lsquo;w&rsquo;,encoding=&lsquo;utf-8&rsquo;) as f2:
file_mtime = os.path.getmtime(fileName) #get timeinfo in float form
file_mtime = datetime.datetime.fromtimestamp(file_mtime) #convert float time into date objective
file_mtime = datetime.datetime.strftime(file_mtime, &lsquo;%Y-%m-%d&rsquo;) #convert date obj. to str in format yyyymmdd
data = f1.read()</p>
<h1 id="data--resub------ntitle-md_filendate-file_mtimedata1">data = re.sub(&quot;&mdash;&quot;,&quot;&mdash;\ntitle: &ldquo;+md_file+&quot;\ndate: &ldquo;+file_mtime,data,1)</h1>
<h1 id="data--resubr___mddata1">data = re.sub(r&rdquo;___(.*).md&rdquo;,&quot;&quot;,data,1)</h1>
<h1 id="data--resub--c--c学习笔记data1">data = re.sub(&quot;- C#&quot;,&quot;- C#学习笔记&quot;,data,1)</h1>
<h1 id="data--resub编程studydata1">data = re.sub(&ldquo;编程&rdquo;,&ldquo;study&rdquo;,data,1)</h1>
<h1 id="data--resub--学习笔记data1">data = re.sub(&quot;- 学习笔记&quot;,&quot;&quot;,data,1)</h1>
<pre><code>        f2.write(data)
    os.remove(fileName)
    os.rename(temp_name,fileName)
except Exception:
    pass
</code></pre>
<h1 id="---">&mdash;</h1>
<h1 id="title-1">title: $$1$$</h1>
<h1 id="date-2022-07-2">date: 2022-07-$$2$$</h1>
<h1 id="tags">tags:</h1>
<h1 id="--c学习笔记">- C#学习笔记</h1>
<h1 id="--study">- study</h1>
<h1 id="----1">&mdash;</h1>
]]></content>
		</item>
		
		<item>
			<title></title>
			<link>https://zhydada.github.io/posts/%E8%AE%BE%E8%AE%A1%E5%B8%88%E8%AE%BF%E8%B0%88%E6%91%98%E8%A6%81___2022-08-22_15-47/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/%E8%AE%BE%E8%AE%A1%E5%B8%88%E8%AE%BF%E8%B0%88%E6%91%98%E8%A6%81___2022-08-22_15-47/</guid>
			<description>飞屋工作室 采访者：优设网程远；受访对象：@飞屋睿UIdesign。 编者按：今天来聊一个让人羡慕的工作，采访对象是优设长期合作作者@飞屋睿UI</description>
			<content type="html"><![CDATA[<h1 id="飞屋工作室">飞屋工作室</h1>
<ul>
<li>采访者：优设网程远；受访对象：@飞屋睿UIdesign。</li>
</ul>
<blockquote>
<p>编者按：今天来聊一个让人羡慕的工作，采访对象是优设长期合作作者@飞屋睿UIdesign ，08年毕业的非科班生，工作后开始自学软件，现在已经有了自己的工作室，生活饱满自由。想知道如何自学、接私单，自由的生活状态是啥样的等等（两手托头仰视羡慕脸），别错过这篇咯</p>
</blockquote>
<ul>
<li><strong>注:</strong> 飞屋工作室是独立设计师网站</li>
</ul>
<blockquote>
<p>你认为自学过程最关键的是什么？</p>
<blockquote>
<p>认识到基础的重要，以及在对于基础训练过程中所经受的忍耐。要面对枯燥的基础知识，很想跳过去直接高屋建瓴，但又深知这不可能。经过基础训练，设计变得越来越好玩。如果没有基本功，恐怕日后的趣味也会减少一半。越是深入，越是发现基础的重要，它就像阳光空气和水一样。你可以说阳光、空气这类东西比较无聊，但它们无处不在，而且也是存在的前提。</p>
</blockquote>
<p>接私活有哪些要注意的（如何避免欠款不还，不断地改改改等）</p>
<blockquote>
<p>接私活，除了项目本身，最重要是做好设计说明。我认为，设计师让客户理解自己的创作过程非常重要。就是一个简单的按钮，也有为什么要放这里而不是放那里，这样的思考过程。当你把设计说明制作成非常优美的文稿给甲方客户，我的经验告诉我，客户几乎无一例外地选择了认同，即使改动也是很微小的细节。这一经验让我也理解到，为什么很多产品都有完全看不懂的产品说明书，其实那就是一种获得你认同的技巧。  其次，我觉得给客户多种方案选择是好事，比如一个设计给三种不同表达方式的方案。我把这个叫做划定选项范围。人都是有比较的心理的。如果只给客户一种选择，他会拿去和现在市面上的其他设计比较，看看是比大部分好还是比大部分差，从而他有成千上万种选择，有时拿不准方向，从而出现改来改去最终改回第一稿的狗血状况。然而如果你只给他三种选择，客户就有了相比较的范围，三选一。如果你的方案都做得出彩，他甚至会来问你他该怎么选择，把选择权教给你。我认为，提高客户的参与感，这是最有效避免客户不断提出改动的方式。</p>
</blockquote>
<p>在哪里可以找到靠谱的私单？</p>
<blockquote>
<p>各种渠道都有机会接到私单，我最靠谱的客户都来自四个字：情投意合。</p>
</blockquote>
<p>您认为对自由设计师而言，最关键的素质是什么？</p>
<blockquote>
<p>终身学习，不忘初心。永远把自己放在一个学习者的位置，接下的每一次设计项目都是一次实战的学习过程，珍惜这一过程，并享受它。你永远不知道未来会发生什么，所以，你就要时刻保持不断学习精进的状态。</p>
</blockquote>
<p>自由设计师和专业设计师相比有哪些得失？可以聊一下您目前的生活状态</p>
<blockquote>
<p>自由设计师也许最大的优势也就是自由，那就同时也意味着更大风险。好好利用自由这一优势，把风险看作一种心性的修炼，让自己更勇敢一点，内心状态会在你的作品中体现出来，你会更少束缚，更多创意。我是属于生活特别规律的人，每天我都会给自己列一份完成任务清单，时间管理对于自由工作者来说非常重要。到了晚上坚决远离工作，看电影、阅读和做运动。</p>
</blockquote>
<p>新人建议</p>
<blockquote>
<p>第一，学好英文，尽量多看国外的设计，尤其是很多大师的作品。除了作品以外，还要去体会大师创作背后的idea，我想这个才是最重要的。<br>
第二，学会阅读和表达，阅读是为了扩大自己的世界。至少看得懂村上春树的幽默，知道一点梵高和莫奈的区别。阅读会潜移默化影响着你对这个世界的理解，也有助于你更加理解人群，这些都会让你的设计看上去更有趣。</p>
</blockquote>
</blockquote>
<h1 id="法国女插画师malika-favre">法国女插画师Malika Favre</h1>
<ul>
<li>原文链接: <a href="https://www.creativeboom.com/features/malika-favre-on-bright-colours-drawing-naughty-things-and-how-to-grow-as-an-illustrator/">https://www.creativeboom.com/features/malika-favre-on-bright-colours-drawing-naughty-things-and-how-to-grow-as-an-illustrator/</a></li>
<li>个人官网: <a href="https://www.malikafavre.com/">https://www.malikafavre.com/</a>
Malika Favre 是一位居于伦敦的插画师。她那大胆、极简的风格，同时也夹杂着一丝幽默感和不按常理出牌的特性，加之她擅长使用负空间和明快的配色，这一切使得她的作品迅速开始成为焦点。</li>
</ul>
<p>在她的平面设计事业生涯的一开始，她就将自己投身于 “少即是多” 这一创作理念的追求。她那别具一格的作品已见于 “Vogue”、“New Yorker” 和“Vanity Fair”等等大牌的杂志页中。</p>
<p>但是，当她还是巴黎郊外的一个青春期女孩时，对未来全无此打算。离开学校以后的 Malika，带着想要成为一名工程师的愿望开始学习数学和物理学。但是情形很快转变，由于她本身对于绘画的热爱带她走向了一条艺术之路。</p>
<blockquote>
<p>你什么时候开始，以及怎样开始经营自己的事业？</p>
<blockquote>
<p>在加入到 Airside 以后，对我来说是个真正的转折点，这是一家跨越多个领域的设计工作室，喜欢采用插画的方式去解决他们的设计和动画方案。在这家工作室长达五年之久，我感觉自己可以开始离开这个 “巢穴” 了，作为独立的插画师开始自己的启航。我尽可能给了他们充足的时间，然后开始我的自由职业生涯，在第一个月里，我也为此存下了一些现金。这是五年前发生的事，此后我从未回顾过过去。</p>
</blockquote>
<p>在早期你面临哪些挑战？你是如何克服它们的？</p>
<blockquote>
<p>我主要的担心是，在突然出现某种状况时，我不得不去接受任何发生在这一过程中的事情。但谢天谢地，我有足够的资金作为支撑，以至于在最早开始时没有发生不得不去做某些妥协的情况。</p>
</blockquote>
<p>当今有许多的插画师正在准备开始自己的事业，对此你有什么值得分享的智慧可助他们成功吗？</p>
<blockquote>
<p>大量的插画师从学校刚毕业就开始成为独立插画师，我认为这样做还为时尚早。学习行业里的经验，学习与客户沟通，时间安排以及讨价还价等都是成功的过程中不可或缺的重要要件。对于成功来说，才华只占百分之十，余下的是人际交往能力，成熟度，对商业的敏感度以及可控的自我。</p>
</blockquote>
<p>有关自我营销，有什么工具、技巧或者资源是你发现最有用的？能透露一些吗……</p>
<blockquote>
<p>第一件事是建立一个非常像样的网站，这能让你的作品自己说话，这也非常易于操作。我第一个网站是和 Cargo 合作，然后拥有一个社区平台可以帮我获得更多曝光率。好像 Behance 和一些其他类似的平台都是不错的方向。</p>
</blockquote>
<blockquote>
<p>（译者按：建议想要推广自己的插画师、设计师等使用飞屋工作室自己研发的轻网站，让作品自己说话，数据由自己管理。有兴趣可留言咨询~）</p>
</blockquote>
<blockquote>
<p>获得一些代理商的支持，当然很好，但是在当今的世界，社交媒体是自我营销的最重要的资源渠道。它完全免费，而且从个人来说，我很喜欢 Instagram，因为我是很视觉化的，但这也得根据不同的人来说。</p>
</blockquote>
<blockquote>
<p>最重要的事情是尽可能多的展示你的作品，获得更多反馈，使自己成长为一个艺术家。</p>
</blockquote>
<p>你这一路走来是否有犯过什么错误以至于到现在还让你感到不安？从这些教训中你获得了什么？</p>
<blockquote>
<p>实话说，真的没有，我不是那种喜欢后悔的类型，当事情发生时，就顺流直下，我倾向于迅速响应并尽快解决。我曾经接手一些不应该接手的客户，当然，有些项目一开始就发现自己此前并没有见过，接手后才发现太迟了。但是我认为，无论是从工作还是生活，你要学会一件事就是犯错是一种必须的经历，只有这样才能进步。所以不管怎样，没有任何后悔。</p>
</blockquote>
<blockquote>
<p>我从中学到最重要的一课就是要寻找到你真正愿意合作的对象，而不需要去看他们是否是大牌。最终，他们将是能决定你的创作结果和品质的人。我比较相信自己的直觉，如果我对某人感觉不好，那么我就不打算接手这份工作，不管对方是多么酷或多么大的品牌。</p>
</blockquote>
</blockquote>
<h1 id="nugi-x-chillhop艺术与漫画访谈">Nugi x Chillhop：艺术与漫画访谈</h1>
<ul>
<li>访谈地址: <a href="https://chillhop.com/nugi-x-chillhop/">https://chillhop.com/nugi-x-chillhop/</a>
<img src="https://chillhop.com/wp-content/uploads/2020/03/nugi_x_chillhop-1024x1024.png" alt=""></li>
<li>2019 年夏天，Chillhop 开始与印尼漫画家 Nugi合作。起初，Nugi 创作了四幅漫画，我们的浣熊倒咖啡、给手机充电、散步。最终，漫画变成了更具情节性和互动性的东西，我们的浣熊参加了 lofi 音乐会和制作人研讨会。</li>
</ul>
<blockquote>
<p>首先介绍一下背景知识，您的艺术历史是怎样的？</p>
<blockquote>
<p>我从小就喜欢画画。我在高中时开始认真对待漫画。我上了美术课，在家乡遇到了一个漫画社区。<br>
我从我的艺术老师和社区里的人那里学到了很多东西，他们在漫画、插图和卡通方面有很多经验。我喜欢做动画，我自己学的。</p>
</blockquote>
<p>除了 Chillhop 相关的漫画，你目前在做什么？</p>
<blockquote>
<p>目前，我是一名自由艺术家。我做佣金和做标志设计。我在漫画大会上出售自己的漫画书和商品。<br>
我也做壁画艺术，比如在咖啡馆的墙上画画，或者根据邻居的要求在街上画一堵墙。<br>
Currently, I am a freelance artist. I do commissions and make logo designs. I sell my own comic books and merchandise at the comic convention. I also do mural art, like drawing on a wall in a cafe, or paint a wall on the street because the neighbourhood requested.</p>
</blockquote>
<p>创作时有哪些工作室必备品？</p>
<blockquote>
<p>我正在使用 Photoshop CC 进行绘图。Sony Vegas 用于动画和视频编辑以及 Wacom 绘图数位板。有时需要加冰的 v60 咖啡。<br>
I am using Photoshop CC for drawing. Sony Vegas for animation and video editing and Wacom drawing pen tablet. Sometimes  v60 coffee with ice will be needed.</p>
</blockquote>
<p>Who are some comic artists you admire?</p>
<blockquote>
<p>Some of them are from the community I have told you, like @wibik_sana @komikman @chesteille @hifzakomik @komiklieur and @tahilalats (he’s now one of the biggest comics artists in Indonesia). Also, I like the style from @randowis @nellunchoj @sarahandersencomics @adamtots @koteri.ink @z_t00n @ulysseadventures @radiomaru @shencomix.</p>
</blockquote>
<p>Do you have any advice for artists working on their craft?</p>
<blockquote>
<p>My advice, in general, is to be always inspired and motivated.<br>
You need to explore your world in order to get them.<br>
As for artists who work in Chillhop, I get inspired by them a lot so keep up the good work!<br>
What is one thing you know now that you wish you knew when you first started with your art?<br>
I was a super shy person (I am still now but improved haha). I was scared and anxious when meeting other people, especially a new one. But the community and my homeschooling friends changed me bit by bit.<br>
I wish I could go back and be brave/confident since then so that I can ask other people more about comics, drawing, and animation. That way I could have started earlier than now.</p>
</blockquote>
</blockquote>
<h1 id="keep-working-keep-thinking-an-art-interview-with-wenyi-geng">Keep Working, Keep Thinking: An Art Interview with Wenyi Geng</h1>
<p><img src="https://chillhop.com/wp-content/uploads/2019/08/daydreams21.jpg" alt=""></p>
<ul>
<li>访谈链接: <a href="https://chillhop.com/wenyi-geng-interview/">https://chillhop.com/wenyi-geng-interview/</a></li>
<li>Wenyi Geng was born in Japan, raised in China, resided in New York for art school, and has now, just recently, moved back to Japan.</li>
<li>The dreamy and surreal illustrator first appeared in the Chillhop catalog with the compilation daydreams released last August. Now, with daydreams 2 set to release on August 21, it was only right that we asked her for a follow-up cover.</li>
</ul>
<blockquote>
<p>If your present self could talk to yourself five years ago, what are some tips you would give? What kind of advice?</p>
<blockquote>
<p>5 years is such a long time but also it feels like just yesterday! Remember where I was and what I was doing back then, I never thought I’d be able to go this far, I didn’t even know what I was doing back then! I was trying everything and was trying to find my position.<br>
So…if I’m able to say something to me five years ago, I guess this is what I would say: just keep doing whatever you are doing and don’t forget where you came from, where your heart belongs and…it is okay to be not okay.<br>
Everything comes and goes, life is hard in a normal way but don’t forget to do what you are supposed to do. Be patient, things will happen.</p>
</blockquote>
<p>Do you often need music when you illustrate, or do you work better in silence?</p>
<blockquote>
<p>With music, absolutely. I need something (sounds) to help me shut down the outside world, plus it’s really hard to find a silent place nowadays [laughs].<br>
I do have a working space but it is really hard to not pay attention to all the surrounding noises, that’s where music helped me a lot.</p>
</blockquote>
<p>How do you mix your time between creating art and marketing yourself? Do you find one more difficult than the other?</p>
<blockquote>
<p>This is a very interesting question, and I think I’m doing a very bad job at marketing myself, the only thing I’m doing to promote myself now is to post whatever things I’ve done online, such as Instagram and Behance and to my website, but this is it, maybe I should do something else to promote myself [laughs]. It is true that it’s really hard to keep the balance between making the artwork and marketing myself, and I guess I have yet to find the best way to do both at the same time.<br>
For the second question, I’m not really sure which one is more difficult because for me they are both very difficult! But in a very different way, it’s like the difference between learning Math and Literature, and of course, you can not say one is harder than the other.</p>
</blockquote>
<p>Is it difficult to find time for yourself while also working for others?</p>
<blockquote>
<p>It’s really really hard to balance between work and life, but I guess I can’t be too greedy on everything. I still remember the feeling when I got my first illustration job, I was so excited and still, I’m really thankful for all the people that are willing to work with me, I can not complain because I’m busy about work.</p>
</blockquote>
<p>If you can, please describe your workspace. What are some essentials while you illustrate?</p>
<blockquote>
<p>Coffee or tea and, of course, some music. I do have a specific set up for my working space, 2 desks–one for my computer and tablet, etc, the other one as a drawing table. It takes up a lot of space! But this is the most important part of my life so it doesn’t bother me so much.</p>
</blockquote>
<p>How important is place in regards to your own creativity?</p>
<blockquote>
<p>I was also worried about this. I was really afraid that if I leave New York, I will lose all of the ideas that I have in my mind, but the truth is I am still who I am, and no matter where I go, my brain and my hands are still here with me. I won’t lose my creativity just because I moved to another place.</p>
</blockquote>
<p>Do you have any further advice or wisdom for artists working on their craft?</p>
<blockquote>
<p>Just keep working, keep thinking, and working as hard as you can and you will never regret it. But don’t destroy your health  !&gt; &gt;</p>
</blockquote>
</blockquote>
]]></content>
		</item>
		
		<item>
			<title>VS的一些操作</title>
			<link>https://zhydada.github.io/posts/visual-studio%E7%9A%84%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C___2022-08-23_09-23/</link>
			<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
			
			<guid>https://zhydada.github.io/posts/visual-studio%E7%9A%84%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C___2022-08-23_09-23/</guid>
			<description>设置用户片段 / 代码片段 vs页面 &amp;gt; 工具 &amp;gt; 代码片段管理器 &amp;gt; 随便找一个地址在里面放片段 代码片段格式如下 &amp;lt;header&amp;gt;会显示在管理器里</description>
			<content type="html"><![CDATA[<blockquote>
<p>设置用户片段 / 代码片段</p>
</blockquote>
<ul>
<li>vs页面 &gt; 工具 &gt; 代码片段管理器 &gt; 随便找一个地址在里面放片段</li>
<li>代码片段<strong>格式</strong>如下
<ul>
<li>&lt;<em><strong>header</strong></em>&gt;会显示在管理器里面, 其中&lt;<em><strong>Shortcut</strong></em>&gt;是触发片段的字段</li>
<li>&lt;<em><strong>Literal</strong></em>&gt;是用来解释变量的, 还应当设置默认值</li>
<li><code>$selected$ $end$</code>这两个不知道为什么但总是一起出现</li>
</ul>
</li>
<li>此外, <em><strong>CDATA</strong></em>的格式不要变动, 在这之间的片段会按照原样式(也有可能是格式化之后的格式)输出</li>
</ul>
<pre tabindex="0"><code>&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;
&lt;CodeSnippets xmlns=&#34;http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet&#34;&gt;
	&lt;CodeSnippet Format=&#34;1.0.0&#34;&gt;
		&lt;Header&gt;
			&lt;Title&gt;for&lt;/Title&gt;
			&lt;Shortcut&gt;for&lt;/Shortcut&gt;
			&lt;Description&gt;for 循环的代码片段&lt;/Description&gt;
			&lt;Author&gt;Microsoft Corporation&lt;/Author&gt;
			&lt;SnippetTypes&gt;
				&lt;SnippetType&gt;Expansion&lt;/SnippetType&gt;
				&lt;SnippetType&gt;SurroundsWith&lt;/SnippetType&gt;
			&lt;/SnippetTypes&gt;
		&lt;/Header&gt;
		&lt;Snippet&gt;
			&lt;Declarations&gt;
				&lt;Literal&gt;
					&lt;ID&gt;index&lt;/ID&gt;
					&lt;Default&gt;i&lt;/Default&gt;
					&lt;ToolTip&gt;索引&lt;/ToolTip&gt;
				&lt;/Literal&gt;
				&lt;Literal&gt;
					&lt;ID&gt;max&lt;/ID&gt;
					&lt;Default&gt;length&lt;/Default&gt;
					&lt;ToolTip&gt;最大长度&lt;/ToolTip&gt;
				&lt;/Literal&gt;
			&lt;/Declarations&gt;
			&lt;Code Language=&#34;csharp&#34;&gt;&lt;![CDATA[for (int $index$ = 0; $index$ &lt; $max$; $index$++)
			{
			$selected$ $end$
			}]]&gt;
			&lt;/Code&gt;
		&lt;/Snippet&gt;
	&lt;/CodeSnippet&gt;
&lt;/CodeSnippets&gt;
</code></pre>]]></content>
		</item>
		
	</channel>
</rss>
